Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * media.c - Media Controller specific ALSA driver code
0004  *
0005  * Copyright (c) 2019 Shuah Khan <shuah@kernel.org>
0006  *
0007  */
0008 
0009 /*
0010  * This file adds Media Controller support to the ALSA driver
0011  * to use the Media Controller API to share the tuner with DVB
0012  * and V4L2 drivers that control the media device.
0013  *
0014  * The media device is created based on the existing quirks framework.
0015  * Using this approach, the media controller API usage can be added for
0016  * a specific device.
0017  */
0018 
0019 #include <linux/init.h>
0020 #include <linux/list.h>
0021 #include <linux/mutex.h>
0022 #include <linux/slab.h>
0023 #include <linux/usb.h>
0024 
0025 #include <sound/pcm.h>
0026 #include <sound/core.h>
0027 
0028 #include "usbaudio.h"
0029 #include "card.h"
0030 #include "mixer.h"
0031 #include "media.h"
0032 
0033 int snd_media_stream_init(struct snd_usb_substream *subs, struct snd_pcm *pcm,
0034               int stream)
0035 {
0036     struct media_device *mdev;
0037     struct media_ctl *mctl;
0038     struct device *pcm_dev = &pcm->streams[stream].dev;
0039     u32 intf_type;
0040     int ret = 0;
0041     u16 mixer_pad;
0042     struct media_entity *entity;
0043 
0044     mdev = subs->stream->chip->media_dev;
0045     if (!mdev)
0046         return 0;
0047 
0048     if (subs->media_ctl)
0049         return 0;
0050 
0051     /* allocate media_ctl */
0052     mctl = kzalloc(sizeof(*mctl), GFP_KERNEL);
0053     if (!mctl)
0054         return -ENOMEM;
0055 
0056     mctl->media_dev = mdev;
0057     if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
0058         intf_type = MEDIA_INTF_T_ALSA_PCM_PLAYBACK;
0059         mctl->media_entity.function = MEDIA_ENT_F_AUDIO_PLAYBACK;
0060         mctl->media_pad.flags = MEDIA_PAD_FL_SOURCE;
0061         mixer_pad = 1;
0062     } else {
0063         intf_type = MEDIA_INTF_T_ALSA_PCM_CAPTURE;
0064         mctl->media_entity.function = MEDIA_ENT_F_AUDIO_CAPTURE;
0065         mctl->media_pad.flags = MEDIA_PAD_FL_SINK;
0066         mixer_pad = 2;
0067     }
0068     mctl->media_entity.name = pcm->name;
0069     media_entity_pads_init(&mctl->media_entity, 1, &mctl->media_pad);
0070     ret =  media_device_register_entity(mctl->media_dev,
0071                         &mctl->media_entity);
0072     if (ret)
0073         goto free_mctl;
0074 
0075     mctl->intf_devnode = media_devnode_create(mdev, intf_type, 0,
0076                           MAJOR(pcm_dev->devt),
0077                           MINOR(pcm_dev->devt));
0078     if (!mctl->intf_devnode) {
0079         ret = -ENOMEM;
0080         goto unregister_entity;
0081     }
0082     mctl->intf_link = media_create_intf_link(&mctl->media_entity,
0083                          &mctl->intf_devnode->intf,
0084                          MEDIA_LNK_FL_ENABLED);
0085     if (!mctl->intf_link) {
0086         ret = -ENOMEM;
0087         goto devnode_remove;
0088     }
0089 
0090     /* create link between mixer and audio */
0091     media_device_for_each_entity(entity, mdev) {
0092         switch (entity->function) {
0093         case MEDIA_ENT_F_AUDIO_MIXER:
0094             ret = media_create_pad_link(entity, mixer_pad,
0095                             &mctl->media_entity, 0,
0096                             MEDIA_LNK_FL_ENABLED);
0097             if (ret)
0098                 goto remove_intf_link;
0099             break;
0100         }
0101     }
0102 
0103     subs->media_ctl = mctl;
0104     return 0;
0105 
0106 remove_intf_link:
0107     media_remove_intf_link(mctl->intf_link);
0108 devnode_remove:
0109     media_devnode_remove(mctl->intf_devnode);
0110 unregister_entity:
0111     media_device_unregister_entity(&mctl->media_entity);
0112 free_mctl:
0113     kfree(mctl);
0114     return ret;
0115 }
0116 
0117 void snd_media_stream_delete(struct snd_usb_substream *subs)
0118 {
0119     struct media_ctl *mctl = subs->media_ctl;
0120 
0121     if (mctl) {
0122         struct media_device *mdev;
0123 
0124         mdev = mctl->media_dev;
0125         if (mdev && media_devnode_is_registered(mdev->devnode)) {
0126             media_devnode_remove(mctl->intf_devnode);
0127             media_device_unregister_entity(&mctl->media_entity);
0128             media_entity_cleanup(&mctl->media_entity);
0129         }
0130         kfree(mctl);
0131         subs->media_ctl = NULL;
0132     }
0133 }
0134 
0135 int snd_media_start_pipeline(struct snd_usb_substream *subs)
0136 {
0137     struct media_ctl *mctl = subs->media_ctl;
0138     int ret = 0;
0139 
0140     if (!mctl)
0141         return 0;
0142 
0143     mutex_lock(&mctl->media_dev->graph_mutex);
0144     if (mctl->media_dev->enable_source)
0145         ret = mctl->media_dev->enable_source(&mctl->media_entity,
0146                              &mctl->media_pipe);
0147     mutex_unlock(&mctl->media_dev->graph_mutex);
0148     return ret;
0149 }
0150 
0151 void snd_media_stop_pipeline(struct snd_usb_substream *subs)
0152 {
0153     struct media_ctl *mctl = subs->media_ctl;
0154 
0155     if (!mctl)
0156         return;
0157 
0158     mutex_lock(&mctl->media_dev->graph_mutex);
0159     if (mctl->media_dev->disable_source)
0160         mctl->media_dev->disable_source(&mctl->media_entity);
0161     mutex_unlock(&mctl->media_dev->graph_mutex);
0162 }
0163 
0164 static int snd_media_mixer_init(struct snd_usb_audio *chip)
0165 {
0166     struct device *ctl_dev = &chip->card->ctl_dev;
0167     struct media_intf_devnode *ctl_intf;
0168     struct usb_mixer_interface *mixer;
0169     struct media_device *mdev = chip->media_dev;
0170     struct media_mixer_ctl *mctl;
0171     u32 intf_type = MEDIA_INTF_T_ALSA_CONTROL;
0172     int ret;
0173 
0174     if (!mdev)
0175         return -ENODEV;
0176 
0177     ctl_intf = chip->ctl_intf_media_devnode;
0178     if (!ctl_intf) {
0179         ctl_intf = media_devnode_create(mdev, intf_type, 0,
0180                         MAJOR(ctl_dev->devt),
0181                         MINOR(ctl_dev->devt));
0182         if (!ctl_intf)
0183             return -ENOMEM;
0184         chip->ctl_intf_media_devnode = ctl_intf;
0185     }
0186 
0187     list_for_each_entry(mixer, &chip->mixer_list, list) {
0188 
0189         if (mixer->media_mixer_ctl)
0190             continue;
0191 
0192         /* allocate media_mixer_ctl */
0193         mctl = kzalloc(sizeof(*mctl), GFP_KERNEL);
0194         if (!mctl)
0195             return -ENOMEM;
0196 
0197         mctl->media_dev = mdev;
0198         mctl->media_entity.function = MEDIA_ENT_F_AUDIO_MIXER;
0199         mctl->media_entity.name = chip->card->mixername;
0200         mctl->media_pad[0].flags = MEDIA_PAD_FL_SINK;
0201         mctl->media_pad[1].flags = MEDIA_PAD_FL_SOURCE;
0202         mctl->media_pad[2].flags = MEDIA_PAD_FL_SOURCE;
0203         media_entity_pads_init(&mctl->media_entity, MEDIA_MIXER_PAD_MAX,
0204                   mctl->media_pad);
0205         ret =  media_device_register_entity(mctl->media_dev,
0206                             &mctl->media_entity);
0207         if (ret) {
0208             kfree(mctl);
0209             return ret;
0210         }
0211 
0212         mctl->intf_link = media_create_intf_link(&mctl->media_entity,
0213                              &ctl_intf->intf,
0214                              MEDIA_LNK_FL_ENABLED);
0215         if (!mctl->intf_link) {
0216             media_device_unregister_entity(&mctl->media_entity);
0217             media_entity_cleanup(&mctl->media_entity);
0218             kfree(mctl);
0219             return -ENOMEM;
0220         }
0221         mctl->intf_devnode = ctl_intf;
0222         mixer->media_mixer_ctl = mctl;
0223     }
0224     return 0;
0225 }
0226 
0227 static void snd_media_mixer_delete(struct snd_usb_audio *chip)
0228 {
0229     struct usb_mixer_interface *mixer;
0230     struct media_device *mdev = chip->media_dev;
0231 
0232     if (!mdev)
0233         return;
0234 
0235     list_for_each_entry(mixer, &chip->mixer_list, list) {
0236         struct media_mixer_ctl *mctl;
0237 
0238         mctl = mixer->media_mixer_ctl;
0239         if (!mixer->media_mixer_ctl)
0240             continue;
0241 
0242         if (media_devnode_is_registered(mdev->devnode)) {
0243             media_device_unregister_entity(&mctl->media_entity);
0244             media_entity_cleanup(&mctl->media_entity);
0245         }
0246         kfree(mctl);
0247         mixer->media_mixer_ctl = NULL;
0248     }
0249     if (media_devnode_is_registered(mdev->devnode))
0250         media_devnode_remove(chip->ctl_intf_media_devnode);
0251     chip->ctl_intf_media_devnode = NULL;
0252 }
0253 
0254 int snd_media_device_create(struct snd_usb_audio *chip,
0255             struct usb_interface *iface)
0256 {
0257     struct media_device *mdev;
0258     struct usb_device *usbdev = interface_to_usbdev(iface);
0259     int ret = 0;
0260 
0261     /* usb-audio driver is probed for each usb interface, and
0262      * there are multiple interfaces per device. Avoid calling
0263      * media_device_usb_allocate() each time usb_audio_probe()
0264      * is called. Do it only once.
0265      */
0266     if (chip->media_dev) {
0267         mdev = chip->media_dev;
0268         goto snd_mixer_init;
0269     }
0270 
0271     mdev = media_device_usb_allocate(usbdev, KBUILD_MODNAME, THIS_MODULE);
0272     if (IS_ERR(mdev))
0273         return -ENOMEM;
0274 
0275     /* save media device - avoid lookups */
0276     chip->media_dev = mdev;
0277 
0278 snd_mixer_init:
0279     /* Create media entities for mixer and control dev */
0280     ret = snd_media_mixer_init(chip);
0281     /* media_device might be registered, print error and continue */
0282     if (ret)
0283         dev_err(&usbdev->dev,
0284             "Couldn't create media mixer entities. Error: %d\n",
0285             ret);
0286 
0287     if (!media_devnode_is_registered(mdev->devnode)) {
0288         /* don't register if snd_media_mixer_init() failed */
0289         if (ret)
0290             goto create_fail;
0291 
0292         /* register media_device */
0293         ret = media_device_register(mdev);
0294 create_fail:
0295         if (ret) {
0296             snd_media_mixer_delete(chip);
0297             media_device_delete(mdev, KBUILD_MODNAME, THIS_MODULE);
0298             /* clear saved media_dev */
0299             chip->media_dev = NULL;
0300             dev_err(&usbdev->dev,
0301                 "Couldn't register media device. Error: %d\n",
0302                 ret);
0303             return ret;
0304         }
0305     }
0306 
0307     return ret;
0308 }
0309 
0310 void snd_media_device_delete(struct snd_usb_audio *chip)
0311 {
0312     struct media_device *mdev = chip->media_dev;
0313     struct snd_usb_stream *stream;
0314 
0315     /* release resources */
0316     list_for_each_entry(stream, &chip->pcm_list, list) {
0317         snd_media_stream_delete(&stream->substream[0]);
0318         snd_media_stream_delete(&stream->substream[1]);
0319     }
0320 
0321     snd_media_mixer_delete(chip);
0322 
0323     if (mdev) {
0324         media_device_delete(mdev, KBUILD_MODNAME, THIS_MODULE);
0325         chip->media_dev = NULL;
0326     }
0327 }