root/sound/usb/hiface/chip.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. hiface_chip_create
  2. hiface_chip_probe
  3. hiface_chip_disconnect

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Linux driver for M2Tech hiFace compatible devices
   4  *
   5  * Copyright 2012-2013 (C) M2TECH S.r.l and Amarula Solutions B.V.
   6  *
   7  * Authors:  Michael Trimarchi <michael@amarulasolutions.com>
   8  *           Antonio Ospite <ao2@amarulasolutions.com>
   9  *
  10  * The driver is based on the work done in TerraTec DMX 6Fire USB
  11  */
  12 
  13 #include <linux/module.h>
  14 #include <linux/slab.h>
  15 #include <sound/initval.h>
  16 
  17 #include "chip.h"
  18 #include "pcm.h"
  19 
  20 MODULE_AUTHOR("Michael Trimarchi <michael@amarulasolutions.com>");
  21 MODULE_AUTHOR("Antonio Ospite <ao2@amarulasolutions.com>");
  22 MODULE_DESCRIPTION("M2Tech hiFace USB-SPDIF audio driver");
  23 MODULE_LICENSE("GPL v2");
  24 MODULE_SUPPORTED_DEVICE("{{M2Tech,Young},"
  25                          "{M2Tech,hiFace},"
  26                          "{M2Tech,North Star},"
  27                          "{M2Tech,W4S Young},"
  28                          "{M2Tech,Corrson},"
  29                          "{M2Tech,AUDIA},"
  30                          "{M2Tech,SL Audio},"
  31                          "{M2Tech,Empirical},"
  32                          "{M2Tech,Rockna},"
  33                          "{M2Tech,Pathos},"
  34                          "{M2Tech,Metronome},"
  35                          "{M2Tech,CAD},"
  36                          "{M2Tech,Audio Esclusive},"
  37                          "{M2Tech,Rotel},"
  38                          "{M2Tech,Eeaudio},"
  39                          "{The Chord Company,CHORD},"
  40                          "{AVA Group A/S,Vitus}}");
  41 
  42 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */
  43 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for card */
  44 static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
  45 
  46 #define DRIVER_NAME "snd-usb-hiface"
  47 #define CARD_NAME "hiFace"
  48 
  49 module_param_array(index, int, NULL, 0444);
  50 MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard.");
  51 module_param_array(id, charp, NULL, 0444);
  52 MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard.");
  53 module_param_array(enable, bool, NULL, 0444);
  54 MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard.");
  55 
  56 static DEFINE_MUTEX(register_mutex);
  57 
  58 struct hiface_vendor_quirk {
  59         const char *device_name;
  60         u8 extra_freq;
  61 };
  62 
  63 static int hiface_chip_create(struct usb_interface *intf,
  64                               struct usb_device *device, int idx,
  65                               const struct hiface_vendor_quirk *quirk,
  66                               struct hiface_chip **rchip)
  67 {
  68         struct snd_card *card = NULL;
  69         struct hiface_chip *chip;
  70         int ret;
  71         int len;
  72 
  73         *rchip = NULL;
  74 
  75         /* if we are here, card can be registered in alsa. */
  76         ret = snd_card_new(&intf->dev, index[idx], id[idx], THIS_MODULE,
  77                            sizeof(*chip), &card);
  78         if (ret < 0) {
  79                 dev_err(&device->dev, "cannot create alsa card.\n");
  80                 return ret;
  81         }
  82 
  83         strlcpy(card->driver, DRIVER_NAME, sizeof(card->driver));
  84 
  85         if (quirk && quirk->device_name)
  86                 strlcpy(card->shortname, quirk->device_name, sizeof(card->shortname));
  87         else
  88                 strlcpy(card->shortname, "M2Tech generic audio", sizeof(card->shortname));
  89 
  90         strlcat(card->longname, card->shortname, sizeof(card->longname));
  91         len = strlcat(card->longname, " at ", sizeof(card->longname));
  92         if (len < sizeof(card->longname))
  93                 usb_make_path(device, card->longname + len,
  94                               sizeof(card->longname) - len);
  95 
  96         chip = card->private_data;
  97         chip->dev = device;
  98         chip->card = card;
  99 
 100         *rchip = chip;
 101         return 0;
 102 }
 103 
 104 static int hiface_chip_probe(struct usb_interface *intf,
 105                              const struct usb_device_id *usb_id)
 106 {
 107         const struct hiface_vendor_quirk *quirk = (struct hiface_vendor_quirk *)usb_id->driver_info;
 108         int ret;
 109         int i;
 110         struct hiface_chip *chip;
 111         struct usb_device *device = interface_to_usbdev(intf);
 112 
 113         ret = usb_set_interface(device, 0, 0);
 114         if (ret != 0) {
 115                 dev_err(&device->dev, "can't set first interface for " CARD_NAME " device.\n");
 116                 return -EIO;
 117         }
 118 
 119         /* check whether the card is already registered */
 120         chip = NULL;
 121         mutex_lock(&register_mutex);
 122 
 123         for (i = 0; i < SNDRV_CARDS; i++)
 124                 if (enable[i])
 125                         break;
 126 
 127         if (i >= SNDRV_CARDS) {
 128                 dev_err(&device->dev, "no available " CARD_NAME " audio device\n");
 129                 ret = -ENODEV;
 130                 goto err;
 131         }
 132 
 133         ret = hiface_chip_create(intf, device, i, quirk, &chip);
 134         if (ret < 0)
 135                 goto err;
 136 
 137         ret = hiface_pcm_init(chip, quirk ? quirk->extra_freq : 0);
 138         if (ret < 0)
 139                 goto err_chip_destroy;
 140 
 141         ret = snd_card_register(chip->card);
 142         if (ret < 0) {
 143                 dev_err(&device->dev, "cannot register " CARD_NAME " card\n");
 144                 goto err_chip_destroy;
 145         }
 146 
 147         mutex_unlock(&register_mutex);
 148 
 149         usb_set_intfdata(intf, chip);
 150         return 0;
 151 
 152 err_chip_destroy:
 153         snd_card_free(chip->card);
 154 err:
 155         mutex_unlock(&register_mutex);
 156         return ret;
 157 }
 158 
 159 static void hiface_chip_disconnect(struct usb_interface *intf)
 160 {
 161         struct hiface_chip *chip;
 162         struct snd_card *card;
 163 
 164         chip = usb_get_intfdata(intf);
 165         if (!chip)
 166                 return;
 167 
 168         card = chip->card;
 169 
 170         /* Make sure that the userspace cannot create new request */
 171         snd_card_disconnect(card);
 172 
 173         hiface_pcm_abort(chip);
 174         snd_card_free_when_closed(card);
 175 }
 176 
 177 static const struct usb_device_id device_table[] = {
 178         {
 179                 USB_DEVICE(0x04b4, 0x0384),
 180                 .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) {
 181                         .device_name = "Young",
 182                         .extra_freq = 1,
 183                 }
 184         },
 185         {
 186                 USB_DEVICE(0x04b4, 0x930b),
 187                 .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) {
 188                         .device_name = "hiFace",
 189                 }
 190         },
 191         {
 192                 USB_DEVICE(0x04b4, 0x931b),
 193                 .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) {
 194                         .device_name = "North Star",
 195                 }
 196         },
 197         {
 198                 USB_DEVICE(0x04b4, 0x931c),
 199                 .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) {
 200                         .device_name = "W4S Young",
 201                 }
 202         },
 203         {
 204                 USB_DEVICE(0x04b4, 0x931d),
 205                 .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) {
 206                         .device_name = "Corrson",
 207                 }
 208         },
 209         {
 210                 USB_DEVICE(0x04b4, 0x931e),
 211                 .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) {
 212                         .device_name = "AUDIA",
 213                 }
 214         },
 215         {
 216                 USB_DEVICE(0x04b4, 0x931f),
 217                 .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) {
 218                         .device_name = "SL Audio",
 219                 }
 220         },
 221         {
 222                 USB_DEVICE(0x04b4, 0x9320),
 223                 .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) {
 224                         .device_name = "Empirical",
 225                 }
 226         },
 227         {
 228                 USB_DEVICE(0x04b4, 0x9321),
 229                 .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) {
 230                         .device_name = "Rockna",
 231                 }
 232         },
 233         {
 234                 USB_DEVICE(0x249c, 0x9001),
 235                 .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) {
 236                         .device_name = "Pathos",
 237                 }
 238         },
 239         {
 240                 USB_DEVICE(0x249c, 0x9002),
 241                 .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) {
 242                         .device_name = "Metronome",
 243                 }
 244         },
 245         {
 246                 USB_DEVICE(0x249c, 0x9006),
 247                 .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) {
 248                         .device_name = "CAD",
 249                 }
 250         },
 251         {
 252                 USB_DEVICE(0x249c, 0x9008),
 253                 .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) {
 254                         .device_name = "Audio Esclusive",
 255                 }
 256         },
 257         {
 258                 USB_DEVICE(0x249c, 0x931c),
 259                 .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) {
 260                         .device_name = "Rotel",
 261                 }
 262         },
 263         {
 264                 USB_DEVICE(0x249c, 0x932c),
 265                 .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) {
 266                         .device_name = "Eeaudio",
 267                 }
 268         },
 269         {
 270                 USB_DEVICE(0x245f, 0x931c),
 271                 .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) {
 272                         .device_name = "CHORD",
 273                 }
 274         },
 275         {
 276                 USB_DEVICE(0x25c6, 0x9002),
 277                 .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) {
 278                         .device_name = "Vitus",
 279                 }
 280         },
 281         {}
 282 };
 283 
 284 MODULE_DEVICE_TABLE(usb, device_table);
 285 
 286 static struct usb_driver hiface_usb_driver = {
 287         .name = DRIVER_NAME,
 288         .probe = hiface_chip_probe,
 289         .disconnect = hiface_chip_disconnect,
 290         .id_table = device_table,
 291 };
 292 
 293 module_usb_driver(hiface_usb_driver);

/* [<][>][^][v][top][bottom][index][help] */