Merge tag 'asoc-v4.9' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound...
authorTakashi Iwai <tiwai@suse.de>
Fri, 30 Sep 2016 16:40:40 +0000 (18:40 +0200)
committerTakashi Iwai <tiwai@suse.de>
Fri, 30 Sep 2016 16:40:40 +0000 (18:40 +0200)
ASoC: Updates for v4.9

Apart from the cleanups done by Morimoto-san this has very much been a
driver focused release with very little generic change:

 - A big factoring out of the simple-card code to allow it to be shared
   more with the rcar generic card from Kuninori Morimoto.
 - Removal of some operations duplicated on the CODEC level, again by
   Kuninori Morimoto.
 - Lots more machine support for x86 systems.
 - New drivers for Nuvoton NAU88C10, Realtek RT5660 and RT5663.

93 files changed:
include/sound/tlv.h
include/uapi/sound/asound.h
include/uapi/sound/tlv.h
sound/aoa/fabrics/layout.c
sound/aoa/soundbus/i2sbus/core.c
sound/core/compress_offload.c
sound/core/pcm_native.c
sound/core/seq/seq_clientmgr.c
sound/core/seq/seq_compat.c
sound/firewire/bebob/Makefile
sound/firewire/bebob/bebob.c
sound/firewire/bebob/bebob.h
sound/firewire/bebob/bebob_terratec.c
sound/firewire/bebob/bebob_yamaha.c [deleted file]
sound/firewire/bebob/bebob_yamaha_terratec.c [new file with mode: 0644]
sound/firewire/dice/dice-pcm.c
sound/firewire/digi00x/digi00x-pcm.c
sound/firewire/oxfw/oxfw-pcm.c
sound/firewire/tascam/tascam-pcm.c
sound/hda/ext/hdac_ext_stream.c
sound/pci/ad1889.c
sound/pci/ali5451/ali5451.c
sound/pci/als300.c
sound/pci/als4000.c
sound/pci/asihpi/asihpi.c
sound/pci/asihpi/hpifunc.c
sound/pci/atiixp.c
sound/pci/atiixp_modem.c
sound/pci/au88x0/au88x0_core.c
sound/pci/aw2/aw2-alsa.c
sound/pci/azt3328.c
sound/pci/bt87x.c
sound/pci/ca0106/ca0106_main.c
sound/pci/cmipci.c
sound/pci/cs4281.c
sound/pci/cs46xx/cs46xx_lib.c
sound/pci/cs46xx/dsp_spos.c
sound/pci/cs5535audio/cs5535audio_pcm.c
sound/pci/ctxfi/ctatc.c
sound/pci/ctxfi/ctpcm.c
sound/pci/ctxfi/ctvmem.c
sound/pci/emu10k1/emu10k1x.c
sound/pci/emu10k1/emupcm.c
sound/pci/emu10k1/p16v.c
sound/pci/ens1370.c
sound/pci/es1938.c
sound/pci/es1968.c
sound/pci/fm801.c
sound/pci/hda/hda_controller.c
sound/pci/hda/patch_ca0132.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_realtek.c
sound/pci/ice1712/ice1712.c
sound/pci/ice1712/ice1724.c
sound/pci/korg1212/korg1212.c
sound/pci/lola/lola_pcm.c
sound/pci/lx6464es/lx6464es.c
sound/pci/maestro3.c
sound/pci/mixart/mixart.c
sound/pci/nm256/nm256.c
sound/pci/oxygen/oxygen_pcm.c
sound/pci/pcxhr/pcxhr.c
sound/pci/riptide/riptide.c
sound/pci/rme32.c
sound/pci/rme96.c
sound/pci/rme9652/hdsp.c
sound/pci/rme9652/hdspm.c
sound/pci/rme9652/rme9652.c
sound/pci/sonicvibes.c
sound/pci/trident/trident_main.c
sound/pci/via82xx.c
sound/pci/via82xx_modem.c
sound/pci/ymfpci/ymfpci_main.c
sound/ppc/snd_ps3.c
sound/soc/intel/baytrail/sst-baytrail-ipc.c
sound/usb/caiaq/audio.c
sound/usb/card.h
sound/usb/endpoint.c
sound/usb/format.c
sound/usb/line6/Kconfig
sound/usb/line6/capture.c
sound/usb/line6/driver.c
sound/usb/line6/driver.h
sound/usb/line6/midi.c
sound/usb/line6/pcm.c
sound/usb/line6/pcm.h
sound/usb/line6/playback.c
sound/usb/line6/pod.c
sound/usb/line6/podhd.c
sound/usb/line6/toneport.c
sound/usb/line6/variax.c
sound/usb/mixer_quirks.c
sound/usb/quirks.c

index df97d19..3677ebb 100644 (file)
  *
  */
 
-/*
- * TLV structure is right behind the struct snd_ctl_tlv:
- *   unsigned int type         - see SNDRV_CTL_TLVT_*
- *   unsigned int length
- *   .... data aligned to sizeof(unsigned int), use
- *        block_length = (length + (sizeof(unsigned int) - 1)) &
- *                       ~(sizeof(unsigned int) - 1)) ....
- */
-
 #include <uapi/sound/tlv.h>
 
-#define TLV_ITEM(type, ...) \
-       (type), TLV_LENGTH(__VA_ARGS__), __VA_ARGS__
-#define TLV_LENGTH(...) \
-       ((unsigned int)sizeof((const unsigned int[]) { __VA_ARGS__ }))
+/* For historical reasons, these macros are aliases to the ones in UAPI. */
+#define TLV_ITEM                       SNDRV_CTL_TLVD_ITEM
+#define TLV_LENGTH                     SNDRV_CTL_TLVD_LENGTH
+
+#define TLV_CONTAINER_ITEM             SNDRV_CTL_TLVD_CONTAINER_ITEM
+#define DECLARE_TLV_CONTAINER          SNDRV_CTL_TLVD_DECLARE_CONTAINER
 
-#define TLV_CONTAINER_ITEM(...) \
-       TLV_ITEM(SNDRV_CTL_TLVT_CONTAINER, __VA_ARGS__)
-#define DECLARE_TLV_CONTAINER(name, ...) \
-       unsigned int name[] = { TLV_CONTAINER_ITEM(__VA_ARGS__) }
+#define TLV_DB_SCALE_MASK              SNDRV_CTL_TLVD_DB_SCALE_MASK
+#define TLV_DB_SCALE_MUTE              SNDRV_CTL_TLVD_DB_SCALE_MUTE
+#define TLV_DB_SCALE_ITEM              SNDRV_CTL_TLVD_DB_SCALE_ITEM
+#define DECLARE_TLV_DB_SCALE           SNDRV_CTL_TLVD_DECLARE_DB_SCALE
 
-#define TLV_DB_SCALE_MASK      0xffff
-#define TLV_DB_SCALE_MUTE      0x10000
-#define TLV_DB_SCALE_ITEM(min, step, mute)                     \
-       TLV_ITEM(SNDRV_CTL_TLVT_DB_SCALE,                       \
-                (min),                                 \
-                ((step) & TLV_DB_SCALE_MASK) |         \
-                       ((mute) ? TLV_DB_SCALE_MUTE : 0))
-#define DECLARE_TLV_DB_SCALE(name, min, step, mute) \
-       unsigned int name[] = { TLV_DB_SCALE_ITEM(min, step, mute) }
+#define TLV_DB_MINMAX_ITEM             SNDRV_CTL_TLVD_DB_MINMAX_ITEM
+#define TLV_DB_MINMAX_MUTE_ITEM                SNDRV_CTL_TLVD_DB_MINMAX_MUTE_ITEM
+#define DECLARE_TLV_DB_MINMAX          SNDRV_CTL_TLVD_DECLARE_DB_MINMAX
+#define DECLARE_TLV_DB_MINMAX_MUTE     SNDRV_CTL_TLVD_DECLARE_DB_MINMAX_MUTE
 
-/* dB scale specified with min/max values instead of step */
-#define TLV_DB_MINMAX_ITEM(min_dB, max_dB)                     \
-       TLV_ITEM(SNDRV_CTL_TLVT_DB_MINMAX, (min_dB), (max_dB))
-#define TLV_DB_MINMAX_MUTE_ITEM(min_dB, max_dB)                        \
-       TLV_ITEM(SNDRV_CTL_TLVT_DB_MINMAX_MUTE, (min_dB), (max_dB))
-#define DECLARE_TLV_DB_MINMAX(name, min_dB, max_dB) \
-       unsigned int name[] = { TLV_DB_MINMAX_ITEM(min_dB, max_dB) }
-#define DECLARE_TLV_DB_MINMAX_MUTE(name, min_dB, max_dB) \
-       unsigned int name[] = { TLV_DB_MINMAX_MUTE_ITEM(min_dB, max_dB) }
+#define TLV_DB_LINEAR_ITEM             SNDRV_CTL_TLVD_DB_LINEAR_ITEM
+#define DECLARE_TLV_DB_LINEAR          SNDRV_CTL_TLVD_DECLARE_DB_LINEAR
 
-/* linear volume between min_dB and max_dB (.01dB unit) */
-#define TLV_DB_LINEAR_ITEM(min_dB, max_dB)                 \
-       TLV_ITEM(SNDRV_CTL_TLVT_DB_LINEAR, (min_dB), (max_dB))
-#define DECLARE_TLV_DB_LINEAR(name, min_dB, max_dB)    \
-       unsigned int name[] = { TLV_DB_LINEAR_ITEM(min_dB, max_dB) }
+#define TLV_DB_RANGE_ITEM              SNDRV_CTL_TLVD_DB_RANGE_ITEM
+#define DECLARE_TLV_DB_RANGE           SNDRV_CTL_TLVD_DECLARE_DB_RANGE
 
-/* dB range container:
- * Items in dB range container must be ordered by their values and by their
- * dB values. This implies that larger values must correspond with larger
- * dB values (which is also required for all other mixer controls).
+#define TLV_DB_GAIN_MUTE               SNDRV_CTL_TLVD_DB_GAIN_MUTE
+
+/*
+ * The below assumes that each item TLV is 4 words like DB_SCALE or LINEAR.
+ * This is an old fasion and obsoleted by commit bf1d1c9b6179("ALSA: tlv: add
+ * DECLARE_TLV_DB_RANGE()").
  */
-/* Each item is: <min> <max> <TLV> */
-#define TLV_DB_RANGE_ITEM(...) \
-       TLV_ITEM(SNDRV_CTL_TLVT_DB_RANGE, __VA_ARGS__)
-#define DECLARE_TLV_DB_RANGE(name, ...) \
-       unsigned int name[] = { TLV_DB_RANGE_ITEM(__VA_ARGS__) }
-/* The below assumes that each item TLV is 4 words like DB_SCALE or LINEAR */
-#define TLV_DB_RANGE_HEAD(num)                 \
+#define TLV_DB_RANGE_HEAD(num) \
        SNDRV_CTL_TLVT_DB_RANGE, 6 * (num) * sizeof(unsigned int)
 
-#define TLV_DB_GAIN_MUTE       -9999999
-
 #endif /* __SOUND_TLV_H */
index 609cadb..be353a7 100644 (file)
@@ -106,9 +106,10 @@ enum {
        SNDRV_HWDEP_IFACE_FW_OXFW,      /* Oxford OXFW970/971 based device */
        SNDRV_HWDEP_IFACE_FW_DIGI00X,   /* Digidesign Digi 002/003 family */
        SNDRV_HWDEP_IFACE_FW_TASCAM,    /* TASCAM FireWire series */
+       SNDRV_HWDEP_IFACE_LINE6,        /* Line6 USB processors */
 
        /* Don't forget to change the following: */
-       SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_FW_TASCAM
+       SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_LINE6
 };
 
 struct snd_hwdep_info {
index ffc4f20..b4df440 100644 (file)
 #define SNDRV_CTL_TLVT_CHMAP_VAR       0x102   /* channels freely swappable */
 #define SNDRV_CTL_TLVT_CHMAP_PAIRED    0x103   /* pair-wise swappable */
 
+/*
+ * TLV structure is right behind the struct snd_ctl_tlv:
+ *   unsigned int type         - see SNDRV_CTL_TLVT_*
+ *   unsigned int length
+ *   .... data aligned to sizeof(unsigned int), use
+ *        block_length = (length + (sizeof(unsigned int) - 1)) &
+ *                       ~(sizeof(unsigned int) - 1)) ....
+ */
+#define SNDRV_CTL_TLVD_ITEM(type, ...) \
+       (type), SNDRV_CTL_TLVD_LENGTH(__VA_ARGS__), __VA_ARGS__
+#define SNDRV_CTL_TLVD_LENGTH(...) \
+       ((unsigned int)sizeof((const unsigned int[]) { __VA_ARGS__ }))
+
+#define SNDRV_CTL_TLVD_CONTAINER_ITEM(...) \
+       SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_CONTAINER, __VA_ARGS__)
+#define SNDRV_CTL_TLVD_DECLARE_CONTAINER(name, ...) \
+       unsigned int name[] = { \
+               SNDRV_CTL_TLVD_CONTAINER_ITEM(__VA_ARGS__) \
+       }
+
+#define SNDRV_CTL_TLVD_DB_SCALE_MASK   0xffff
+#define SNDRV_CTL_TLVD_DB_SCALE_MUTE   0x10000
+#define SNDRV_CTL_TLVD_DB_SCALE_ITEM(min, step, mute) \
+       SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_SCALE, \
+                           (min), \
+                           ((step) & SNDRV_CTL_TLVD_DB_SCALE_MASK) | \
+                            ((mute) ? SNDRV_CTL_TLVD_DB_SCALE_MUTE : 0))
+#define SNDRV_CTL_TLVD_DECLARE_DB_SCALE(name, min, step, mute) \
+       unsigned int name[] = { \
+               SNDRV_CTL_TLVD_DB_SCALE_ITEM(min, step, mute) \
+       }
+
+/* dB scale specified with min/max values instead of step */
+#define SNDRV_CTL_TLVD_DB_MINMAX_ITEM(min_dB, max_dB) \
+       SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_MINMAX, (min_dB), (max_dB))
+#define SNDRV_CTL_TLVD_DB_MINMAX_MUTE_ITEM(min_dB, max_dB) \
+       SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_MINMAX_MUTE, (min_dB), (max_dB))
+#define SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(name, min_dB, max_dB) \
+       unsigned int name[] = { \
+               SNDRV_CTL_TLVD_DB_MINMAX_ITEM(min_dB, max_dB) \
+       }
+#define SNDRV_CTL_TLVD_DECLARE_DB_MINMAX_MUTE(name, min_dB, max_dB) \
+       unsigned int name[] = { \
+               SNDRV_CTL_TLVD_DB_MINMAX_MUTE_ITEM(min_dB, max_dB) \
+       }
+
+/* linear volume between min_dB and max_dB (.01dB unit) */
+#define SNDRV_CTL_TLVD_DB_LINEAR_ITEM(min_dB, max_dB) \
+       SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_LINEAR, (min_dB), (max_dB))
+#define SNDRV_CTL_TLVD_DECLARE_DB_LINEAR(name, min_dB, max_dB) \
+       unsigned int name[] = { \
+               SNDRV_CTL_TLVD_DB_LINEAR_ITEM(min_dB, max_dB) \
+       }
+
+/* dB range container:
+ * Items in dB range container must be ordered by their values and by their
+ * dB values. This implies that larger values must correspond with larger
+ * dB values (which is also required for all other mixer controls).
+ */
+/* Each item is: <min> <max> <TLV> */
+#define SNDRV_CTL_TLVD_DB_RANGE_ITEM(...) \
+       SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_RANGE, __VA_ARGS__)
+#define SNDRV_CTL_TLVD_DECLARE_DB_RANGE(name, ...) \
+       unsigned int name[] = { \
+               SNDRV_CTL_TLVD_DB_RANGE_ITEM(__VA_ARGS__) \
+       }
+
+#define SNDRV_CTL_TLVD_DB_GAIN_MUTE    -9999999
+
 #endif
index 8f71f7e..a0c4a5d 100644 (file)
@@ -112,6 +112,7 @@ MODULE_ALIAS("sound-layout-100");
 
 MODULE_ALIAS("aoa-device-id-14");
 MODULE_ALIAS("aoa-device-id-22");
+MODULE_ALIAS("aoa-device-id-31");
 MODULE_ALIAS("aoa-device-id-35");
 MODULE_ALIAS("aoa-device-id-44");
 
@@ -362,6 +363,13 @@ static struct layout layouts[] = {
                .connections = tas_connections_nolineout,
          },
        },
+       /* PowerBook6,1 */
+       { .device_id = 31,
+         .codecs[0] = {
+               .name = "tas",
+               .connections = tas_connections_nolineout,
+         },
+       },
        /* PowerBook6,5 */
        { .device_id = 44,
          .codecs[0] = {
@@ -1161,12 +1169,7 @@ static struct soundbus_driver aoa_soundbus_driver = {
 
 static int __init aoa_fabric_layout_init(void)
 {
-       int err;
-
-       err = soundbus_register_driver(&aoa_soundbus_driver);
-       if (err)
-               return err;
-       return 0;
+       return soundbus_register_driver(&aoa_soundbus_driver);
 }
 
 static void __exit aoa_fabric_layout_exit(void)
index 1cbf210..000b585 100644 (file)
@@ -197,7 +197,7 @@ static int i2sbus_add_dev(struct macio_dev *macio,
                         * so restrict to those we do handle for now.
                         */
                        if (id && (*id == 22 || *id == 14 || *id == 35 ||
-                                  *id == 44)) {
+                                  *id == 31 || *id == 44)) {
                                snprintf(dev->sound.modalias, 32,
                                         "aoa-device-id-%d", *id);
                                ok = 1;
index 2c49848..fec1dfd 100644 (file)
@@ -553,13 +553,9 @@ snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg)
                 * we should allow parameter change only when stream has been
                 * opened not in other cases
                 */
-               params = kmalloc(sizeof(*params), GFP_KERNEL);
-               if (!params)
-                       return -ENOMEM;
-               if (copy_from_user(params, (void __user *)arg, sizeof(*params))) {
-                       retval = -EFAULT;
-                       goto out;
-               }
+               params = memdup_user((void __user *)arg, sizeof(*params));
+               if (IS_ERR(params))
+                       return PTR_ERR(params);
 
                retval = snd_compress_check_input(params);
                if (retval)
@@ -784,7 +780,7 @@ static int snd_compress_wait_for_drain(struct snd_compr_stream *stream)
        ret = wait_event_interruptible(stream->runtime->sleep,
                        (stream->runtime->state != SNDRV_PCM_STATE_DRAINING));
        if (ret == -ERESTARTSYS)
-               pr_debug("wait aborted by a signal");
+               pr_debug("wait aborted by a signal\n");
        else if (ret)
                pr_debug("wait for drain failed with %d\n", ret);
 
@@ -966,7 +962,7 @@ static int snd_compress_dev_register(struct snd_device *device)
                                  compr->card, compr->device,
                                  &snd_compr_file_ops, compr, &compr->dev);
        if (ret < 0) {
-               pr_err("snd_register_device failed\n %d", ret);
+               pr_err("snd_register_device failed %d\n", ret);
                return ret;
        }
        return ret;
index c61fd50..9d33c1e 100644 (file)
@@ -2637,9 +2637,11 @@ static int snd_pcm_hwsync(struct snd_pcm_substream *substream)
                        break;
                /* Fall through */
        case SNDRV_PCM_STATE_PREPARED:
-       case SNDRV_PCM_STATE_SUSPENDED:
                err = 0;
                break;
+       case SNDRV_PCM_STATE_SUSPENDED:
+               err = -ESTRPIPE;
+               break;
        case SNDRV_PCM_STATE_XRUN:
                err = -EPIPE;
                break;
index d6d9419..4c93520 100644 (file)
@@ -85,21 +85,6 @@ static int snd_seq_deliver_single_event(struct snd_seq_client *client,
                                        struct snd_seq_event *event,
                                        int filter, int atomic, int hop);
 
-/*
- */
-static inline mm_segment_t snd_enter_user(void)
-{
-       mm_segment_t fs = get_fs();
-       set_fs(get_ds());
-       return fs;
-}
-
-static inline void snd_leave_user(mm_segment_t fs)
-{
-       set_fs(fs);
-}
-
 /*
  */
 static inline unsigned short snd_seq_file_flags(struct file *file)
@@ -1128,59 +1113,69 @@ static unsigned int snd_seq_poll(struct file *file, poll_table * wait)
 
 /*-----------------------------------------------------*/
 
+static int snd_seq_ioctl_pversion(struct snd_seq_client *client, void *arg)
+{
+       int *pversion = arg;
+
+       *pversion = SNDRV_SEQ_VERSION;
+       return 0;
+}
+
+static int snd_seq_ioctl_client_id(struct snd_seq_client *client, void *arg)
+{
+       int *client_id = arg;
+
+       *client_id = client->number;
+       return 0;
+}
 
 /* SYSTEM_INFO ioctl() */
-static int snd_seq_ioctl_system_info(struct snd_seq_client *client, void __user *arg)
+static int snd_seq_ioctl_system_info(struct snd_seq_client *client, void *arg)
 {
-       struct snd_seq_system_info info;
+       struct snd_seq_system_info *info = arg;
 
-       memset(&info, 0, sizeof(info));
+       memset(info, 0, sizeof(*info));
        /* fill the info fields */
-       info.queues = SNDRV_SEQ_MAX_QUEUES;
-       info.clients = SNDRV_SEQ_MAX_CLIENTS;
-       info.ports = SNDRV_SEQ_MAX_PORTS;
-       info.channels = 256;    /* fixed limit */
-       info.cur_clients = client_usage.cur;
-       info.cur_queues = snd_seq_queue_get_cur_queues();
-
-       if (copy_to_user(arg, &info, sizeof(info)))
-               return -EFAULT;
+       info->queues = SNDRV_SEQ_MAX_QUEUES;
+       info->clients = SNDRV_SEQ_MAX_CLIENTS;
+       info->ports = SNDRV_SEQ_MAX_PORTS;
+       info->channels = 256;   /* fixed limit */
+       info->cur_clients = client_usage.cur;
+       info->cur_queues = snd_seq_queue_get_cur_queues();
+
        return 0;
 }
 
 
 /* RUNNING_MODE ioctl() */
-static int snd_seq_ioctl_running_mode(struct snd_seq_client *client, void __user *arg)
+static int snd_seq_ioctl_running_mode(struct snd_seq_client *client, void  *arg)
 {
-       struct snd_seq_running_info info;
+       struct snd_seq_running_info *info = arg;
        struct snd_seq_client *cptr;
        int err = 0;
 
-       if (copy_from_user(&info, arg, sizeof(info)))
-               return -EFAULT;
-
        /* requested client number */
-       cptr = snd_seq_client_use_ptr(info.client);
+       cptr = snd_seq_client_use_ptr(info->client);
        if (cptr == NULL)
                return -ENOENT;         /* don't change !!! */
 
 #ifdef SNDRV_BIG_ENDIAN
-       if (! info.big_endian) {
+       if (!info->big_endian) {
                err = -EINVAL;
                goto __err;
        }
 #else
-       if (info.big_endian) {
+       if (info->big_endian) {
                err = -EINVAL;
                goto __err;
        }
 
 #endif
-       if (info.cpu_mode > sizeof(long)) {
+       if (info->cpu_mode > sizeof(long)) {
                err = -EINVAL;
                goto __err;
        }
-       cptr->convert32 = (info.cpu_mode < sizeof(long));
+       cptr->convert32 = (info->cpu_mode < sizeof(long));
  __err:
        snd_seq_client_unlock(cptr);
        return err;
@@ -1214,51 +1209,43 @@ static void get_client_info(struct snd_seq_client *cptr,
 }
 
 static int snd_seq_ioctl_get_client_info(struct snd_seq_client *client,
-                                        void __user *arg)
+                                        void *arg)
 {
+       struct snd_seq_client_info *client_info = arg;
        struct snd_seq_client *cptr;
-       struct snd_seq_client_info client_info;
-
-       if (copy_from_user(&client_info, arg, sizeof(client_info)))
-               return -EFAULT;
 
        /* requested client number */
-       cptr = snd_seq_client_use_ptr(client_info.client);
+       cptr = snd_seq_client_use_ptr(client_info->client);
        if (cptr == NULL)
                return -ENOENT;         /* don't change !!! */
 
-       get_client_info(cptr, &client_info);
+       get_client_info(cptr, client_info);
        snd_seq_client_unlock(cptr);
 
-       if (copy_to_user(arg, &client_info, sizeof(client_info)))
-               return -EFAULT;
        return 0;
 }
 
 
 /* CLIENT_INFO ioctl() */
 static int snd_seq_ioctl_set_client_info(struct snd_seq_client *client,
-                                        void __user *arg)
+                                        void *arg)
 {
-       struct snd_seq_client_info client_info;
-
-       if (copy_from_user(&client_info, arg, sizeof(client_info)))
-               return -EFAULT;
+       struct snd_seq_client_info *client_info = arg;
 
        /* it is not allowed to set the info fields for an another client */
-       if (client->number != client_info.client)
+       if (client->number != client_info->client)
                return -EPERM;
        /* also client type must be set now */
-       if (client->type != client_info.type)
+       if (client->type != client_info->type)
                return -EINVAL;
 
        /* fill the info fields */
-       if (client_info.name[0])
-               strlcpy(client->name, client_info.name, sizeof(client->name));
+       if (client_info->name[0])
+               strlcpy(client->name, client_info->name, sizeof(client->name));
 
-       client->filter = client_info.filter;
-       client->event_lost = client_info.event_lost;
-       memcpy(client->event_filter, client_info.event_filter, 32);
+       client->filter = client_info->filter;
+       client->event_lost = client_info->event_lost;
+       memcpy(client->event_filter, client_info->event_filter, 32);
 
        return 0;
 }
@@ -1267,30 +1254,26 @@ static int snd_seq_ioctl_set_client_info(struct snd_seq_client *client,
 /* 
  * CREATE PORT ioctl() 
  */
-static int snd_seq_ioctl_create_port(struct snd_seq_client *client,
-                                    void __user *arg)
+static int snd_seq_ioctl_create_port(struct snd_seq_client *client, void *arg)
 {
+       struct snd_seq_port_info *info = arg;
        struct snd_seq_client_port *port;
-       struct snd_seq_port_info info;
        struct snd_seq_port_callback *callback;
 
-       if (copy_from_user(&info, arg, sizeof(info)))
-               return -EFAULT;
-
        /* it is not allowed to create the port for an another client */
-       if (info.addr.client != client->number)
+       if (info->addr.client != client->number)
                return -EPERM;
 
-       port = snd_seq_create_port(client, (info.flags & SNDRV_SEQ_PORT_FLG_GIVEN_PORT) ? info.addr.port : -1);
+       port = snd_seq_create_port(client, (info->flags & SNDRV_SEQ_PORT_FLG_GIVEN_PORT) ? info->addr.port : -1);
        if (port == NULL)
                return -ENOMEM;
 
-       if (client->type == USER_CLIENT && info.kernel) {
+       if (client->type == USER_CLIENT && info->kernel) {
                snd_seq_delete_port(client, port->addr.port);
                return -EINVAL;
        }
        if (client->type == KERNEL_CLIENT) {
-               if ((callback = info.kernel) != NULL) {
+               if ((callback = info->kernel) != NULL) {
                        if (callback->owner)
                                port->owner = callback->owner;
                        port->private_data = callback->private_data;
@@ -1303,37 +1286,29 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client,
                }
        }
 
-       info.addr = port->addr;
+       info->addr = port->addr;
 
-       snd_seq_set_port_info(port, &info);
+       snd_seq_set_port_info(port, info);
        snd_seq_system_client_ev_port_start(port->addr.client, port->addr.port);
 
-       if (copy_to_user(arg, &info, sizeof(info)))
-               return -EFAULT;
-
        return 0;
 }
 
 /* 
  * DELETE PORT ioctl() 
  */
-static int snd_seq_ioctl_delete_port(struct snd_seq_client *client,
-                                    void __user *arg)
+static int snd_seq_ioctl_delete_port(struct snd_seq_client *client, void *arg)
 {
-       struct snd_seq_port_info info;
+       struct snd_seq_port_info *info = arg;
        int err;
 
-       /* set passed parameters */
-       if (copy_from_user(&info, arg, sizeof(info)))
-               return -EFAULT;
-       
        /* it is not allowed to remove the port for an another client */
-       if (info.addr.client != client->number)
+       if (info->addr.client != client->number)
                return -EPERM;
 
-       err = snd_seq_delete_port(client, info.addr.port);
+       err = snd_seq_delete_port(client, info->addr.port);
        if (err >= 0)
-               snd_seq_system_client_ev_port_exit(client->number, info.addr.port);
+               snd_seq_system_client_ev_port_exit(client->number, info->addr.port);
        return err;
 }
 
@@ -1341,32 +1316,27 @@ static int snd_seq_ioctl_delete_port(struct snd_seq_client *client,
 /* 
  * GET_PORT_INFO ioctl() (on any client) 
  */
-static int snd_seq_ioctl_get_port_info(struct snd_seq_client *client,
-                                      void __user *arg)
+static int snd_seq_ioctl_get_port_info(struct snd_seq_client *client, void *arg)
 {
+       struct snd_seq_port_info *info = arg;
        struct snd_seq_client *cptr;
        struct snd_seq_client_port *port;
-       struct snd_seq_port_info info;
 
-       if (copy_from_user(&info, arg, sizeof(info)))
-               return -EFAULT;
-       cptr = snd_seq_client_use_ptr(info.addr.client);
+       cptr = snd_seq_client_use_ptr(info->addr.client);
        if (cptr == NULL)
                return -ENXIO;
 
-       port = snd_seq_port_use_ptr(cptr, info.addr.port);
+       port = snd_seq_port_use_ptr(cptr, info->addr.port);
        if (port == NULL) {
                snd_seq_client_unlock(cptr);
                return -ENOENT;                 /* don't change */
        }
 
        /* get port info */
-       snd_seq_get_port_info(port, &info);
+       snd_seq_get_port_info(port, info);
        snd_seq_port_unlock(port);
        snd_seq_client_unlock(cptr);
 
-       if (copy_to_user(arg, &info, sizeof(info)))
-               return -EFAULT;
        return 0;
 }
 
@@ -1374,20 +1344,16 @@ static int snd_seq_ioctl_get_port_info(struct snd_seq_client *client,
 /* 
  * SET_PORT_INFO ioctl() (only ports on this/own client) 
  */
-static int snd_seq_ioctl_set_port_info(struct snd_seq_client *client,
-                                      void __user *arg)
+static int snd_seq_ioctl_set_port_info(struct snd_seq_client *client, void *arg)
 {
+       struct snd_seq_port_info *info = arg;
        struct snd_seq_client_port *port;
-       struct snd_seq_port_info info;
-
-       if (copy_from_user(&info, arg, sizeof(info)))
-               return -EFAULT;
 
-       if (info.addr.client != client->number) /* only set our own ports ! */
+       if (info->addr.client != client->number) /* only set our own ports ! */
                return -EPERM;
-       port = snd_seq_port_use_ptr(client, info.addr.port);
+       port = snd_seq_port_use_ptr(client, info->addr.port);
        if (port) {
-               snd_seq_set_port_info(port, &info);
+               snd_seq_set_port_info(port, info);
                snd_seq_port_unlock(port);
        }
        return 0;
@@ -1453,34 +1419,31 @@ int snd_seq_client_notify_subscription(int client, int port,
  * add to port's subscription list IOCTL interface 
  */
 static int snd_seq_ioctl_subscribe_port(struct snd_seq_client *client,
-                                       void __user *arg)
+                                       void *arg)
 {
+       struct snd_seq_port_subscribe *subs = arg;
        int result = -EINVAL;
        struct snd_seq_client *receiver = NULL, *sender = NULL;
        struct snd_seq_client_port *sport = NULL, *dport = NULL;
-       struct snd_seq_port_subscribe subs;
-
-       if (copy_from_user(&subs, arg, sizeof(subs)))
-               return -EFAULT;
 
-       if ((receiver = snd_seq_client_use_ptr(subs.dest.client)) == NULL)
+       if ((receiver = snd_seq_client_use_ptr(subs->dest.client)) == NULL)
                goto __end;
-       if ((sender = snd_seq_client_use_ptr(subs.sender.client)) == NULL)
+       if ((sender = snd_seq_client_use_ptr(subs->sender.client)) == NULL)
                goto __end;
-       if ((sport = snd_seq_port_use_ptr(sender, subs.sender.port)) == NULL)
+       if ((sport = snd_seq_port_use_ptr(sender, subs->sender.port)) == NULL)
                goto __end;
-       if ((dport = snd_seq_port_use_ptr(receiver, subs.dest.port)) == NULL)
+       if ((dport = snd_seq_port_use_ptr(receiver, subs->dest.port)) == NULL)
                goto __end;
 
-       result = check_subscription_permission(client, sport, dport, &subs);
+       result = check_subscription_permission(client, sport, dport, subs);
        if (result < 0)
                goto __end;
 
        /* connect them */
-       result = snd_seq_port_connect(client, sender, sport, receiver, dport, &subs);
+       result = snd_seq_port_connect(client, sender, sport, receiver, dport, subs);
        if (! result) /* broadcast announce */
                snd_seq_client_notify_subscription(SNDRV_SEQ_ADDRESS_SUBSCRIBERS, 0,
-                                                  &subs, SNDRV_SEQ_EVENT_PORT_SUBSCRIBED);
+                                                  subs, SNDRV_SEQ_EVENT_PORT_SUBSCRIBED);
       __end:
        if (sport)
                snd_seq_port_unlock(sport);
@@ -1498,33 +1461,30 @@ static int snd_seq_ioctl_subscribe_port(struct snd_seq_client *client,
  * remove from port's subscription list 
  */
 static int snd_seq_ioctl_unsubscribe_port(struct snd_seq_client *client,
-                                         void __user *arg)
+                                         void *arg)
 {
+       struct snd_seq_port_subscribe *subs = arg;
        int result = -ENXIO;
        struct snd_seq_client *receiver = NULL, *sender = NULL;
        struct snd_seq_client_port *sport = NULL, *dport = NULL;
-       struct snd_seq_port_subscribe subs;
-
-       if (copy_from_user(&subs, arg, sizeof(subs)))
-               return -EFAULT;
 
-       if ((receiver = snd_seq_client_use_ptr(subs.dest.client)) == NULL)
+       if ((receiver = snd_seq_client_use_ptr(subs->dest.client)) == NULL)
                goto __end;
-       if ((sender = snd_seq_client_use_ptr(subs.sender.client)) == NULL)
+       if ((sender = snd_seq_client_use_ptr(subs->sender.client)) == NULL)
                goto __end;
-       if ((sport = snd_seq_port_use_ptr(sender, subs.sender.port)) == NULL)
+       if ((sport = snd_seq_port_use_ptr(sender, subs->sender.port)) == NULL)
                goto __end;
-       if ((dport = snd_seq_port_use_ptr(receiver, subs.dest.port)) == NULL)
+       if ((dport = snd_seq_port_use_ptr(receiver, subs->dest.port)) == NULL)
                goto __end;
 
-       result = check_subscription_permission(client, sport, dport, &subs);
+       result = check_subscription_permission(client, sport, dport, subs);
        if (result < 0)
                goto __end;
 
-       result = snd_seq_port_disconnect(client, sender, sport, receiver, dport, &subs);
+       result = snd_seq_port_disconnect(client, sender, sport, receiver, dport, subs);
        if (! result) /* broadcast announce */
                snd_seq_client_notify_subscription(SNDRV_SEQ_ADDRESS_SUBSCRIBERS, 0,
-                                                  &subs, SNDRV_SEQ_EVENT_PORT_UNSUBSCRIBED);
+                                                  subs, SNDRV_SEQ_EVENT_PORT_UNSUBSCRIBED);
       __end:
        if (sport)
                snd_seq_port_unlock(sport);
@@ -1539,17 +1499,13 @@ static int snd_seq_ioctl_unsubscribe_port(struct snd_seq_client *client,
 
 
 /* CREATE_QUEUE ioctl() */
-static int snd_seq_ioctl_create_queue(struct snd_seq_client *client,
-                                     void __user *arg)
+static int snd_seq_ioctl_create_queue(struct snd_seq_client *client, void *arg)
 {
-       struct snd_seq_queue_info info;
+       struct snd_seq_queue_info *info = arg;
        int result;
        struct snd_seq_queue *q;
 
-       if (copy_from_user(&info, arg, sizeof(info)))
-               return -EFAULT;
-
-       result = snd_seq_queue_alloc(client->number, info.locked, info.flags);
+       result = snd_seq_queue_alloc(client->number, info->locked, info->flags);
        if (result < 0)
                return result;
 
@@ -1557,181 +1513,150 @@ static int snd_seq_ioctl_create_queue(struct snd_seq_client *client,
        if (q == NULL)
                return -EINVAL;
 
-       info.queue = q->queue;
-       info.locked = q->locked;
-       info.owner = q->owner;
+       info->queue = q->queue;
+       info->locked = q->locked;
+       info->owner = q->owner;
 
        /* set queue name */
-       if (! info.name[0])
-               snprintf(info.name, sizeof(info.name), "Queue-%d", q->queue);
-       strlcpy(q->name, info.name, sizeof(q->name));
+       if (!info->name[0])
+               snprintf(info->name, sizeof(info->name), "Queue-%d", q->queue);
+       strlcpy(q->name, info->name, sizeof(q->name));
        queuefree(q);
 
-       if (copy_to_user(arg, &info, sizeof(info)))
-               return -EFAULT;
-
        return 0;
 }
 
 /* DELETE_QUEUE ioctl() */
-static int snd_seq_ioctl_delete_queue(struct snd_seq_client *client,
-                                     void __user *arg)
+static int snd_seq_ioctl_delete_queue(struct snd_seq_client *client, void *arg)
 {
-       struct snd_seq_queue_info info;
-
-       if (copy_from_user(&info, arg, sizeof(info)))
-               return -EFAULT;
+       struct snd_seq_queue_info *info = arg;
 
-       return snd_seq_queue_delete(client->number, info.queue);
+       return snd_seq_queue_delete(client->number, info->queue);
 }
 
 /* GET_QUEUE_INFO ioctl() */
 static int snd_seq_ioctl_get_queue_info(struct snd_seq_client *client,
-                                       void __user *arg)
+                                       void *arg)
 {
-       struct snd_seq_queue_info info;
+       struct snd_seq_queue_info *info = arg;
        struct snd_seq_queue *q;
 
-       if (copy_from_user(&info, arg, sizeof(info)))
-               return -EFAULT;
-
-       q = queueptr(info.queue);
+       q = queueptr(info->queue);
        if (q == NULL)
                return -EINVAL;
 
-       memset(&info, 0, sizeof(info));
-       info.queue = q->queue;
-       info.owner = q->owner;
-       info.locked = q->locked;
-       strlcpy(info.name, q->name, sizeof(info.name));
+       memset(info, 0, sizeof(*info));
+       info->queue = q->queue;
+       info->owner = q->owner;
+       info->locked = q->locked;
+       strlcpy(info->name, q->name, sizeof(info->name));
        queuefree(q);
 
-       if (copy_to_user(arg, &info, sizeof(info)))
-               return -EFAULT;
-
        return 0;
 }
 
 /* SET_QUEUE_INFO ioctl() */
 static int snd_seq_ioctl_set_queue_info(struct snd_seq_client *client,
-                                       void __user *arg)
+                                       void *arg)
 {
-       struct snd_seq_queue_info info;
+       struct snd_seq_queue_info *info = arg;
        struct snd_seq_queue *q;
 
-       if (copy_from_user(&info, arg, sizeof(info)))
-               return -EFAULT;
-
-       if (info.owner != client->number)
+       if (info->owner != client->number)
                return -EINVAL;
 
        /* change owner/locked permission */
-       if (snd_seq_queue_check_access(info.queue, client->number)) {
-               if (snd_seq_queue_set_owner(info.queue, client->number, info.locked) < 0)
+       if (snd_seq_queue_check_access(info->queue, client->number)) {
+               if (snd_seq_queue_set_owner(info->queue, client->number, info->locked) < 0)
                        return -EPERM;
-               if (info.locked)
-                       snd_seq_queue_use(info.queue, client->number, 1);
+               if (info->locked)
+                       snd_seq_queue_use(info->queue, client->number, 1);
        } else {
                return -EPERM;
        }       
 
-       q = queueptr(info.queue);
+       q = queueptr(info->queue);
        if (! q)
                return -EINVAL;
        if (q->owner != client->number) {
                queuefree(q);
                return -EPERM;
        }
-       strlcpy(q->name, info.name, sizeof(q->name));
+       strlcpy(q->name, info->name, sizeof(q->name));
        queuefree(q);
 
        return 0;
 }
 
 /* GET_NAMED_QUEUE ioctl() */
-static int snd_seq_ioctl_get_named_queue(struct snd_seq_client *client, void __user *arg)
+static int snd_seq_ioctl_get_named_queue(struct snd_seq_client *client,
+                                        void *arg)
 {
-       struct snd_seq_queue_info info;
+       struct snd_seq_queue_info *info = arg;
        struct snd_seq_queue *q;
 
-       if (copy_from_user(&info, arg, sizeof(info)))
-               return -EFAULT;
-
-       q = snd_seq_queue_find_name(info.name);
+       q = snd_seq_queue_find_name(info->name);
        if (q == NULL)
                return -EINVAL;
-       info.queue = q->queue;
-       info.owner = q->owner;
-       info.locked = q->locked;
+       info->queue = q->queue;
+       info->owner = q->owner;
+       info->locked = q->locked;
        queuefree(q);
 
-       if (copy_to_user(arg, &info, sizeof(info)))
-               return -EFAULT;
-
        return 0;
 }
 
 /* GET_QUEUE_STATUS ioctl() */
 static int snd_seq_ioctl_get_queue_status(struct snd_seq_client *client,
-                                         void __user *arg)
+                                         void *arg)
 {
-       struct snd_seq_queue_status status;
+       struct snd_seq_queue_status *status = arg;
        struct snd_seq_queue *queue;
        struct snd_seq_timer *tmr;
 
-       if (copy_from_user(&status, arg, sizeof(status)))
-               return -EFAULT;
-
-       queue = queueptr(status.queue);
+       queue = queueptr(status->queue);
        if (queue == NULL)
                return -EINVAL;
-       memset(&status, 0, sizeof(status));
-       status.queue = queue->queue;
+       memset(status, 0, sizeof(*status));
+       status->queue = queue->queue;
        
        tmr = queue->timer;
-       status.events = queue->tickq->cells + queue->timeq->cells;
+       status->events = queue->tickq->cells + queue->timeq->cells;
 
-       status.time = snd_seq_timer_get_cur_time(tmr);
-       status.tick = snd_seq_timer_get_cur_tick(tmr);
+       status->time = snd_seq_timer_get_cur_time(tmr);
+       status->tick = snd_seq_timer_get_cur_tick(tmr);
 
-       status.running = tmr->running;
+       status->running = tmr->running;
 
-       status.flags = queue->flags;
+       status->flags = queue->flags;
        queuefree(queue);
 
-       if (copy_to_user(arg, &status, sizeof(status)))
-               return -EFAULT;
        return 0;
 }
 
 
 /* GET_QUEUE_TEMPO ioctl() */
 static int snd_seq_ioctl_get_queue_tempo(struct snd_seq_client *client,
-                                        void __user *arg)
+                                        void *arg)
 {
-       struct snd_seq_queue_tempo tempo;
+       struct snd_seq_queue_tempo *tempo = arg;
        struct snd_seq_queue *queue;
        struct snd_seq_timer *tmr;
 
-       if (copy_from_user(&tempo, arg, sizeof(tempo)))
-               return -EFAULT;
-
-       queue = queueptr(tempo.queue);
+       queue = queueptr(tempo->queue);
        if (queue == NULL)
                return -EINVAL;
-       memset(&tempo, 0, sizeof(tempo));
-       tempo.queue = queue->queue;
+       memset(tempo, 0, sizeof(*tempo));
+       tempo->queue = queue->queue;
        
        tmr = queue->timer;
 
-       tempo.tempo = tmr->tempo;
-       tempo.ppq = tmr->ppq;
-       tempo.skew_value = tmr->skew;
-       tempo.skew_base = tmr->skew_base;
+       tempo->tempo = tmr->tempo;
+       tempo->ppq = tmr->ppq;
+       tempo->skew_value = tmr->skew;
+       tempo->skew_base = tmr->skew_base;
        queuefree(queue);
 
-       if (copy_to_user(arg, &tempo, sizeof(tempo)))
-               return -EFAULT;
        return 0;
 }
 
@@ -1747,31 +1672,25 @@ int snd_seq_set_queue_tempo(int client, struct snd_seq_queue_tempo *tempo)
 EXPORT_SYMBOL(snd_seq_set_queue_tempo);
 
 static int snd_seq_ioctl_set_queue_tempo(struct snd_seq_client *client,
-                                        void __user *arg)
+                                        void *arg)
 {
+       struct snd_seq_queue_tempo *tempo = arg;
        int result;
-       struct snd_seq_queue_tempo tempo;
-
-       if (copy_from_user(&tempo, arg, sizeof(tempo)))
-               return -EFAULT;
 
-       result = snd_seq_set_queue_tempo(client->number, &tempo);
+       result = snd_seq_set_queue_tempo(client->number, tempo);
        return result < 0 ? result : 0;
 }
 
 
 /* GET_QUEUE_TIMER ioctl() */
 static int snd_seq_ioctl_get_queue_timer(struct snd_seq_client *client,
-                                        void __user *arg)
+                                        void *arg)
 {
-       struct snd_seq_queue_timer timer;
+       struct snd_seq_queue_timer *timer = arg;
        struct snd_seq_queue *queue;
        struct snd_seq_timer *tmr;
 
-       if (copy_from_user(&timer, arg, sizeof(timer)))
-               return -EFAULT;
-
-       queue = queueptr(timer.queue);
+       queue = queueptr(timer->queue);
        if (queue == NULL)
                return -EINVAL;
 
@@ -1780,41 +1699,36 @@ static int snd_seq_ioctl_get_queue_timer(struct snd_seq_client *client,
                return -ERESTARTSYS;
        }
        tmr = queue->timer;
-       memset(&timer, 0, sizeof(timer));
-       timer.queue = queue->queue;
+       memset(timer, 0, sizeof(*timer));
+       timer->queue = queue->queue;
 
-       timer.type = tmr->type;
+       timer->type = tmr->type;
        if (tmr->type == SNDRV_SEQ_TIMER_ALSA) {
-               timer.u.alsa.id = tmr->alsa_id;
-               timer.u.alsa.resolution = tmr->preferred_resolution;
+               timer->u.alsa.id = tmr->alsa_id;
+               timer->u.alsa.resolution = tmr->preferred_resolution;
        }
        mutex_unlock(&queue->timer_mutex);
        queuefree(queue);
        
-       if (copy_to_user(arg, &timer, sizeof(timer)))
-               return -EFAULT;
        return 0;
 }
 
 
 /* SET_QUEUE_TIMER ioctl() */
 static int snd_seq_ioctl_set_queue_timer(struct snd_seq_client *client,
-                                        void __user *arg)
+                                        void *arg)
 {
+       struct snd_seq_queue_timer *timer = arg;
        int result = 0;
-       struct snd_seq_queue_timer timer;
-
-       if (copy_from_user(&timer, arg, sizeof(timer)))
-               return -EFAULT;
 
-       if (timer.type != SNDRV_SEQ_TIMER_ALSA)
+       if (timer->type != SNDRV_SEQ_TIMER_ALSA)
                return -EINVAL;
 
-       if (snd_seq_queue_check_access(timer.queue, client->number)) {
+       if (snd_seq_queue_check_access(timer->queue, client->number)) {
                struct snd_seq_queue *q;
                struct snd_seq_timer *tmr;
 
-               q = queueptr(timer.queue);
+               q = queueptr(timer->queue);
                if (q == NULL)
                        return -ENXIO;
                if (mutex_lock_interruptible(&q->timer_mutex)) {
@@ -1822,13 +1736,13 @@ static int snd_seq_ioctl_set_queue_timer(struct snd_seq_client *client,
                        return -ERESTARTSYS;
                }
                tmr = q->timer;
-               snd_seq_queue_timer_close(timer.queue);
-               tmr->type = timer.type;
+               snd_seq_queue_timer_close(timer->queue);
+               tmr->type = timer->type;
                if (tmr->type == SNDRV_SEQ_TIMER_ALSA) {
-                       tmr->alsa_id = timer.u.alsa.id;
-                       tmr->preferred_resolution = timer.u.alsa.resolution;
+                       tmr->alsa_id = timer->u.alsa.id;
+                       tmr->preferred_resolution = timer->u.alsa.resolution;
                }
-               result = snd_seq_queue_timer_open(timer.queue);
+               result = snd_seq_queue_timer_open(timer->queue);
                mutex_unlock(&q->timer_mutex);
                queuefree(q);
        } else {
@@ -1841,38 +1755,30 @@ static int snd_seq_ioctl_set_queue_timer(struct snd_seq_client *client,
 
 /* GET_QUEUE_CLIENT ioctl() */
 static int snd_seq_ioctl_get_queue_client(struct snd_seq_client *client,
-                                         void __user *arg)
+                                         void *arg)
 {
-       struct snd_seq_queue_client info;
+       struct snd_seq_queue_client *info = arg;
        int used;
 
-       if (copy_from_user(&info, arg, sizeof(info)))
-               return -EFAULT;
-
-       used = snd_seq_queue_is_used(info.queue, client->number);
+       used = snd_seq_queue_is_used(info->queue, client->number);
        if (used < 0)
                return -EINVAL;
-       info.used = used;
-       info.client = client->number;
+       info->used = used;
+       info->client = client->number;
 
-       if (copy_to_user(arg, &info, sizeof(info)))
-               return -EFAULT;
        return 0;
 }
 
 
 /* SET_QUEUE_CLIENT ioctl() */
 static int snd_seq_ioctl_set_queue_client(struct snd_seq_client *client,
-                                         void __user *arg)
+                                         void *arg)
 {
+       struct snd_seq_queue_client *info = arg;
        int err;
-       struct snd_seq_queue_client info;
-
-       if (copy_from_user(&info, arg, sizeof(info)))
-               return -EFAULT;
 
-       if (info.used >= 0) {
-               err = snd_seq_queue_use(info.queue, client->number, info.used);
+       if (info->used >= 0) {
+               err = snd_seq_queue_use(info->queue, client->number, info->used);
                if (err < 0)
                        return err;
        }
@@ -1883,78 +1789,70 @@ static int snd_seq_ioctl_set_queue_client(struct snd_seq_client *client,
 
 /* GET_CLIENT_POOL ioctl() */
 static int snd_seq_ioctl_get_client_pool(struct snd_seq_client *client,
-                                        void __user *arg)
+                                        void *arg)
 {
-       struct snd_seq_client_pool info;
+       struct snd_seq_client_pool *info = arg;
        struct snd_seq_client *cptr;
 
-       if (copy_from_user(&info, arg, sizeof(info)))
-               return -EFAULT;
-
-       cptr = snd_seq_client_use_ptr(info.client);
+       cptr = snd_seq_client_use_ptr(info->client);
        if (cptr == NULL)
                return -ENOENT;
-       memset(&info, 0, sizeof(info));
-       info.client = cptr->number;
-       info.output_pool = cptr->pool->size;
-       info.output_room = cptr->pool->room;
-       info.output_free = info.output_pool;
-       info.output_free = snd_seq_unused_cells(cptr->pool);
+       memset(info, 0, sizeof(*info));
+       info->client = cptr->number;
+       info->output_pool = cptr->pool->size;
+       info->output_room = cptr->pool->room;
+       info->output_free = info->output_pool;
+       info->output_free = snd_seq_unused_cells(cptr->pool);
        if (cptr->type == USER_CLIENT) {
-               info.input_pool = cptr->data.user.fifo_pool_size;
-               info.input_free = info.input_pool;
+               info->input_pool = cptr->data.user.fifo_pool_size;
+               info->input_free = info->input_pool;
                if (cptr->data.user.fifo)
-                       info.input_free = snd_seq_unused_cells(cptr->data.user.fifo->pool);
+                       info->input_free = snd_seq_unused_cells(cptr->data.user.fifo->pool);
        } else {
-               info.input_pool = 0;
-               info.input_free = 0;
+               info->input_pool = 0;
+               info->input_free = 0;
        }
        snd_seq_client_unlock(cptr);
        
-       if (copy_to_user(arg, &info, sizeof(info)))
-               return -EFAULT;
        return 0;
 }
 
 /* SET_CLIENT_POOL ioctl() */
 static int snd_seq_ioctl_set_client_pool(struct snd_seq_client *client,
-                                        void __user *arg)
+                                        void *arg)
 {
-       struct snd_seq_client_pool info;
+       struct snd_seq_client_pool *info = arg;
        int rc;
 
-       if (copy_from_user(&info, arg, sizeof(info)))
-               return -EFAULT;
-
-       if (client->number != info.client)
+       if (client->number != info->client)
                return -EINVAL; /* can't change other clients */
 
-       if (info.output_pool >= 1 && info.output_pool <= SNDRV_SEQ_MAX_EVENTS &&
+       if (info->output_pool >= 1 && info->output_pool <= SNDRV_SEQ_MAX_EVENTS &&
            (! snd_seq_write_pool_allocated(client) ||
-            info.output_pool != client->pool->size)) {
+            info->output_pool != client->pool->size)) {
                if (snd_seq_write_pool_allocated(client)) {
                        /* remove all existing cells */
                        snd_seq_queue_client_leave_cells(client->number);
                        snd_seq_pool_done(client->pool);
                }
-               client->pool->size = info.output_pool;
+               client->pool->size = info->output_pool;
                rc = snd_seq_pool_init(client->pool);
                if (rc < 0)
                        return rc;
        }
        if (client->type == USER_CLIENT && client->data.user.fifo != NULL &&
-           info.input_pool >= 1 &&
-           info.input_pool <= SNDRV_SEQ_MAX_CLIENT_EVENTS &&
-           info.input_pool != client->data.user.fifo_pool_size) {
+           info->input_pool >= 1 &&
+           info->input_pool <= SNDRV_SEQ_MAX_CLIENT_EVENTS &&
+           info->input_pool != client->data.user.fifo_pool_size) {
                /* change pool size */
-               rc = snd_seq_fifo_resize(client->data.user.fifo, info.input_pool);
+               rc = snd_seq_fifo_resize(client->data.user.fifo, info->input_pool);
                if (rc < 0)
                        return rc;
-               client->data.user.fifo_pool_size = info.input_pool;
+               client->data.user.fifo_pool_size = info->input_pool;
        }
-       if (info.output_room >= 1 &&
-           info.output_room <= client->pool->size) {
-               client->pool->room  = info.output_room;
+       if (info->output_room >= 1 &&
+           info->output_room <= client->pool->size) {
+               client->pool->room  = info->output_room;
        }
 
        return snd_seq_ioctl_get_client_pool(client, arg);
@@ -1963,17 +1861,14 @@ static int snd_seq_ioctl_set_client_pool(struct snd_seq_client *client,
 
 /* REMOVE_EVENTS ioctl() */
 static int snd_seq_ioctl_remove_events(struct snd_seq_client *client,
-                                      void __user *arg)
+                                      void *arg)
 {
-       struct snd_seq_remove_events info;
-
-       if (copy_from_user(&info, arg, sizeof(info)))
-               return -EFAULT;
+       struct snd_seq_remove_events *info = arg;
 
        /*
         * Input mostly not implemented XXX.
         */
-       if (info.remove_mode & SNDRV_SEQ_REMOVE_INPUT) {
+       if (info->remove_mode & SNDRV_SEQ_REMOVE_INPUT) {
                /*
                 * No restrictions so for a user client we can clear
                 * the whole fifo
@@ -1982,8 +1877,8 @@ static int snd_seq_ioctl_remove_events(struct snd_seq_client *client,
                        snd_seq_fifo_clear(client->data.user.fifo);
        }
 
-       if (info.remove_mode & SNDRV_SEQ_REMOVE_OUTPUT)
-               snd_seq_queue_remove_cells(client->number, &info);
+       if (info->remove_mode & SNDRV_SEQ_REMOVE_OUTPUT)
+               snd_seq_queue_remove_cells(client->number, info);
 
        return 0;
 }
@@ -1993,26 +1888,23 @@ static int snd_seq_ioctl_remove_events(struct snd_seq_client *client,
  * get subscription info
  */
 static int snd_seq_ioctl_get_subscription(struct snd_seq_client *client,
-                                         void __user *arg)
+                                         void *arg)
 {
+       struct snd_seq_port_subscribe *subs = arg;
        int result;
        struct snd_seq_client *sender = NULL;
        struct snd_seq_client_port *sport = NULL;
-       struct snd_seq_port_subscribe subs;
        struct snd_seq_subscribers *p;
 
-       if (copy_from_user(&subs, arg, sizeof(subs)))
-               return -EFAULT;
-
        result = -EINVAL;
-       if ((sender = snd_seq_client_use_ptr(subs.sender.client)) == NULL)
+       if ((sender = snd_seq_client_use_ptr(subs->sender.client)) == NULL)
                goto __end;
-       if ((sport = snd_seq_port_use_ptr(sender, subs.sender.port)) == NULL)
+       if ((sport = snd_seq_port_use_ptr(sender, subs->sender.port)) == NULL)
                goto __end;
-       p = snd_seq_port_get_subscription(&sport->c_src, &subs.dest);
+       p = snd_seq_port_get_subscription(&sport->c_src, &subs->dest);
        if (p) {
                result = 0;
-               subs = p->info;
+               *subs = p->info;
        } else
                result = -ENOENT;
 
@@ -2021,10 +1913,7 @@ static int snd_seq_ioctl_get_subscription(struct snd_seq_client *client,
                snd_seq_port_unlock(sport);
        if (sender)
                snd_seq_client_unlock(sender);
-       if (result >= 0) {
-               if (copy_to_user(arg, &subs, sizeof(subs)))
-                       return -EFAULT;
-       }
+
        return result;
 }
 
@@ -2032,26 +1921,22 @@ static int snd_seq_ioctl_get_subscription(struct snd_seq_client *client,
 /*
  * get subscription info - check only its presence
  */
-static int snd_seq_ioctl_query_subs(struct snd_seq_client *client,
-                                   void __user *arg)
+static int snd_seq_ioctl_query_subs(struct snd_seq_client *client, void *arg)
 {
+       struct snd_seq_query_subs *subs = arg;
        int result = -ENXIO;
        struct snd_seq_client *cptr = NULL;
        struct snd_seq_client_port *port = NULL;
-       struct snd_seq_query_subs subs;
        struct snd_seq_port_subs_info *group;
        struct list_head *p;
        int i;
 
-       if (copy_from_user(&subs, arg, sizeof(subs)))
-               return -EFAULT;
-
-       if ((cptr = snd_seq_client_use_ptr(subs.root.client)) == NULL)
+       if ((cptr = snd_seq_client_use_ptr(subs->root.client)) == NULL)
                goto __end;
-       if ((port = snd_seq_port_use_ptr(cptr, subs.root.port)) == NULL)
+       if ((port = snd_seq_port_use_ptr(cptr, subs->root.port)) == NULL)
                goto __end;
 
-       switch (subs.type) {
+       switch (subs->type) {
        case SNDRV_SEQ_QUERY_SUBS_READ:
                group = &port->c_src;
                break;
@@ -2064,22 +1949,22 @@ static int snd_seq_ioctl_query_subs(struct snd_seq_client *client,
 
        down_read(&group->list_mutex);
        /* search for the subscriber */
-       subs.num_subs = group->count;
+       subs->num_subs = group->count;
        i = 0;
        result = -ENOENT;
        list_for_each(p, &group->list_head) {
-               if (i++ == subs.index) {
+               if (i++ == subs->index) {
                        /* found! */
                        struct snd_seq_subscribers *s;
-                       if (subs.type == SNDRV_SEQ_QUERY_SUBS_READ) {
+                       if (subs->type == SNDRV_SEQ_QUERY_SUBS_READ) {
                                s = list_entry(p, struct snd_seq_subscribers, src_list);
-                               subs.addr = s->info.dest;
+                               subs->addr = s->info.dest;
                        } else {
                                s = list_entry(p, struct snd_seq_subscribers, dest_list);
-                               subs.addr = s->info.sender;
+                               subs->addr = s->info.sender;
                        }
-                       subs.flags = s->info.flags;
-                       subs.queue = s->info.queue;
+                       subs->flags = s->info.flags;
+                       subs->queue = s->info.queue;
                        result = 0;
                        break;
                }
@@ -2091,10 +1976,7 @@ static int snd_seq_ioctl_query_subs(struct snd_seq_client *client,
                snd_seq_port_unlock(port);
        if (cptr)
                snd_seq_client_unlock(cptr);
-       if (result >= 0) {
-               if (copy_to_user(arg, &subs, sizeof(subs)))
-                       return -EFAULT;
-       }
+
        return result;
 }
 
@@ -2103,31 +1985,26 @@ static int snd_seq_ioctl_query_subs(struct snd_seq_client *client,
  * query next client
  */
 static int snd_seq_ioctl_query_next_client(struct snd_seq_client *client,
-                                          void __user *arg)
+                                          void *arg)
 {
+       struct snd_seq_client_info *info = arg;
        struct snd_seq_client *cptr = NULL;
-       struct snd_seq_client_info info;
-
-       if (copy_from_user(&info, arg, sizeof(info)))
-               return -EFAULT;
 
        /* search for next client */
-       info.client++;
-       if (info.client < 0)
-               info.client = 0;
-       for (; info.client < SNDRV_SEQ_MAX_CLIENTS; info.client++) {
-               cptr = snd_seq_client_use_ptr(info.client);
+       info->client++;
+       if (info->client < 0)
+               info->client = 0;
+       for (; info->client < SNDRV_SEQ_MAX_CLIENTS; info->client++) {
+               cptr = snd_seq_client_use_ptr(info->client);
                if (cptr)
                        break; /* found */
        }
        if (cptr == NULL)
                return -ENOENT;
 
-       get_client_info(cptr, &info);
+       get_client_info(cptr, info);
        snd_seq_client_unlock(cptr);
 
-       if (copy_to_user(arg, &info, sizeof(info)))
-               return -EFAULT;
        return 0;
 }
 
@@ -2135,43 +2012,41 @@ static int snd_seq_ioctl_query_next_client(struct snd_seq_client *client,
  * query next port
  */
 static int snd_seq_ioctl_query_next_port(struct snd_seq_client *client,
-                                        void __user *arg)
+                                        void *arg)
 {
+       struct snd_seq_port_info *info = arg;
        struct snd_seq_client *cptr;
        struct snd_seq_client_port *port = NULL;
-       struct snd_seq_port_info info;
 
-       if (copy_from_user(&info, arg, sizeof(info)))
-               return -EFAULT;
-       cptr = snd_seq_client_use_ptr(info.addr.client);
+       cptr = snd_seq_client_use_ptr(info->addr.client);
        if (cptr == NULL)
                return -ENXIO;
 
        /* search for next port */
-       info.addr.port++;
-       port = snd_seq_port_query_nearest(cptr, &info);
+       info->addr.port++;
+       port = snd_seq_port_query_nearest(cptr, info);
        if (port == NULL) {
                snd_seq_client_unlock(cptr);
                return -ENOENT;
        }
 
        /* get port info */
-       info.addr = port->addr;
-       snd_seq_get_port_info(port, &info);
+       info->addr = port->addr;
+       snd_seq_get_port_info(port, info);
        snd_seq_port_unlock(port);
        snd_seq_client_unlock(cptr);
 
-       if (copy_to_user(arg, &info, sizeof(info)))
-               return -EFAULT;
        return 0;
 }
 
 /* -------------------------------------------------------- */
 
-static struct seq_ioctl_table {
+static const struct ioctl_handler {
        unsigned int cmd;
-       int (*func)(struct snd_seq_client *client, void __user * arg);
-} ioctl_tables[] = {
+       int (*func)(struct snd_seq_client *client, void *arg);
+} ioctl_handlers[] = {
+       { SNDRV_SEQ_IOCTL_PVERSION, snd_seq_ioctl_pversion },
+       { SNDRV_SEQ_IOCTL_CLIENT_ID, snd_seq_ioctl_client_id },
        { SNDRV_SEQ_IOCTL_SYSTEM_INFO, snd_seq_ioctl_system_info },
        { SNDRV_SEQ_IOCTL_RUNNING_MODE, snd_seq_ioctl_running_mode },
        { SNDRV_SEQ_IOCTL_GET_CLIENT_INFO, snd_seq_ioctl_get_client_info },
@@ -2204,40 +2079,65 @@ static struct seq_ioctl_table {
        { 0, NULL },
 };
 
-static int snd_seq_do_ioctl(struct snd_seq_client *client, unsigned int cmd,
-                           void __user *arg)
+static long snd_seq_ioctl(struct file *file, unsigned int cmd,
+                         unsigned long arg)
 {
-       struct seq_ioctl_table *p;
+       struct snd_seq_client *client = file->private_data;
+       /* To use kernel stack for ioctl data. */
+       union {
+               int pversion;
+               int client_id;
+               struct snd_seq_system_info      system_info;
+               struct snd_seq_running_info     running_info;
+               struct snd_seq_client_info      client_info;
+               struct snd_seq_port_info        port_info;
+               struct snd_seq_port_subscribe   port_subscribe;
+               struct snd_seq_queue_info       queue_info;
+               struct snd_seq_queue_status     queue_status;
+               struct snd_seq_queue_tempo      tempo;
+               struct snd_seq_queue_timer      queue_timer;
+               struct snd_seq_queue_client     queue_client;
+               struct snd_seq_client_pool      client_pool;
+               struct snd_seq_remove_events    remove_events;
+               struct snd_seq_query_subs       query_subs;
+       } buf;
+       const struct ioctl_handler *handler;
+       unsigned long size;
+       int err;
 
-       switch (cmd) {
-       case SNDRV_SEQ_IOCTL_PVERSION:
-               /* return sequencer version number */
-               return put_user(SNDRV_SEQ_VERSION, (int __user *)arg) ? -EFAULT : 0;
-       case SNDRV_SEQ_IOCTL_CLIENT_ID:
-               /* return the id of this client */
-               return put_user(client->number, (int __user *)arg) ? -EFAULT : 0;
-       }
+       if (snd_BUG_ON(!client))
+               return -ENXIO;
 
-       if (! arg)
-               return -EFAULT;
-       for (p = ioctl_tables; p->cmd; p++) {
-               if (p->cmd == cmd)
-                       return p->func(client, arg);
+       for (handler = ioctl_handlers; handler->cmd > 0; ++handler) {
+               if (handler->cmd == cmd)
+                       break;
        }
-       pr_debug("ALSA: seq unknown ioctl() 0x%x (type='%c', number=0x%02x)\n",
-                  cmd, _IOC_TYPE(cmd), _IOC_NR(cmd));
-       return -ENOTTY;
-}
+       if (handler->cmd == 0)
+               return -ENOTTY;
 
+       memset(&buf, 0, sizeof(buf));
 
-static long snd_seq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
-       struct snd_seq_client *client = file->private_data;
+       /*
+        * All of ioctl commands for ALSA sequencer get an argument of size
+        * within 13 bits. We can safely pick up the size from the command.
+        */
+       size = _IOC_SIZE(handler->cmd);
+       if (handler->cmd & IOC_IN) {
+               if (copy_from_user(&buf, (const void __user *)arg, size))
+                       return -EFAULT;
+       }
 
-       if (snd_BUG_ON(!client))
-               return -ENXIO;
-               
-       return snd_seq_do_ioctl(client, cmd, (void __user *) arg);
+       err = handler->func(client, &buf);
+       if (err >= 0) {
+               /* Some commands includes a bug in 'dir' field. */
+               if (handler->cmd == SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT ||
+                   handler->cmd == SNDRV_SEQ_IOCTL_SET_CLIENT_POOL ||
+                   (handler->cmd & IOC_OUT))
+                       if (copy_to_user((void __user *)arg, &buf, size))
+                               return -EFAULT;
+       }
+
+       return err;
 }
 
 #ifdef CONFIG_COMPAT
@@ -2423,23 +2323,35 @@ int snd_seq_kernel_client_dispatch(int client, struct snd_seq_event * ev,
 
 EXPORT_SYMBOL(snd_seq_kernel_client_dispatch);
 
-/*
- * exported, called by kernel clients to perform same functions as with
- * userland ioctl() 
+/**
+ * snd_seq_kernel_client_ctl - operate a command for a client with data in
+ *                            kernel space.
+ * @clientid:  A numerical ID for a client.
+ * @cmd:       An ioctl(2) command for ALSA sequencer operation.
+ * @arg:       A pointer to data in kernel space.
+ *
+ * Against its name, both kernel/application client can be handled by this
+ * kernel API. A pointer of 'arg' argument should be in kernel space.
+ *
+ * Return: 0 at success. Negative error code at failure.
  */
 int snd_seq_kernel_client_ctl(int clientid, unsigned int cmd, void *arg)
 {
+       const struct ioctl_handler *handler;
        struct snd_seq_client *client;
-       mm_segment_t fs;
-       int result;
 
        client = clientptr(clientid);
        if (client == NULL)
                return -ENXIO;
-       fs = snd_enter_user();
-       result = snd_seq_do_ioctl(client, cmd, (void __force __user *)arg);
-       snd_leave_user(fs);
-       return result;
+
+       for (handler = ioctl_handlers; handler->cmd > 0; ++handler) {
+               if (handler->cmd == cmd)
+                       return handler->func(client, arg);
+       }
+
+       pr_debug("ALSA: seq unknown ioctl() 0x%x (type='%c', number=0x%02x)\n",
+                cmd, _IOC_TYPE(cmd), _IOC_NR(cmd));
+       return -ENOTTY;
 }
 
 EXPORT_SYMBOL(snd_seq_kernel_client_ctl);
index 6517590..fce5697 100644 (file)
@@ -47,7 +47,6 @@ static int snd_seq_call_port_info_ioctl(struct snd_seq_client *client, unsigned
 {
        int err = -EFAULT;
        struct snd_seq_port_info *data;
-       mm_segment_t fs;
 
        data = kmalloc(sizeof(*data), GFP_KERNEL);
        if (!data)
@@ -59,9 +58,7 @@ static int snd_seq_call_port_info_ioctl(struct snd_seq_client *client, unsigned
                goto error;
        data->kernel = NULL;
 
-       fs = snd_enter_user();
-       err = snd_seq_do_ioctl(client, cmd, data);
-       snd_leave_user(fs);
+       err = snd_seq_kernel_client_ctl(client->number, cmd, &data);
        if (err < 0)
                goto error;
 
@@ -123,7 +120,7 @@ static long snd_seq_ioctl_compat(struct file *file, unsigned int cmd, unsigned l
        case SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION:
        case SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT:
        case SNDRV_SEQ_IOCTL_RUNNING_MODE:
-               return snd_seq_do_ioctl(client, cmd, argp);
+               return snd_seq_ioctl(file, cmd, arg);
        case SNDRV_SEQ_IOCTL_CREATE_PORT32:
                return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_CREATE_PORT, argp);
        case SNDRV_SEQ_IOCTL_DELETE_PORT32:
index af7ed66..dd45486 100644 (file)
@@ -1,4 +1,5 @@
 snd-bebob-objs := bebob_command.o bebob_stream.o bebob_proc.o bebob_midi.o \
-                 bebob_pcm.o bebob_hwdep.o bebob_terratec.o bebob_yamaha.o \
-                 bebob_focusrite.o bebob_maudio.o bebob.o
+                 bebob_pcm.o bebob_hwdep.o bebob_terratec.o \
+                 bebob_yamaha_terratec.o bebob_focusrite.o bebob_maudio.o \
+                 bebob.o
 obj-$(CONFIG_SND_BEBOB) += snd-bebob.o
index f7e2cbd..3469ac1 100644 (file)
@@ -458,17 +458,17 @@ static const struct ieee1394_device_id bebob_id_table[] = {
        /* TerraTec Electronic GmbH, PHASE 88 Rack FW */
        SND_BEBOB_DEV_ENTRY(VEN_TERRATEC, 0x00000003, &phase88_rack_spec),
        /* TerraTec Electronic GmbH, PHASE 24 FW */
-       SND_BEBOB_DEV_ENTRY(VEN_TERRATEC, 0x00000004, &phase24_series_spec),
+       SND_BEBOB_DEV_ENTRY(VEN_TERRATEC, 0x00000004, &yamaha_terratec_spec),
        /* TerraTec Electronic GmbH, Phase X24 FW */
-       SND_BEBOB_DEV_ENTRY(VEN_TERRATEC, 0x00000007, &phase24_series_spec),
+       SND_BEBOB_DEV_ENTRY(VEN_TERRATEC, 0x00000007, &yamaha_terratec_spec),
        /* TerraTec Electronic GmbH, EWS MIC2/MIC8 */
        SND_BEBOB_DEV_ENTRY(VEN_TERRATEC, 0x00000005, &spec_normal),
        /* Terratec Electronic GmbH, Aureon 7.1 Firewire */
        SND_BEBOB_DEV_ENTRY(VEN_TERRATEC, 0x00000002, &spec_normal),
        /* Yamaha, GO44 */
-       SND_BEBOB_DEV_ENTRY(VEN_YAMAHA, 0x0010000b, &yamaha_go_spec),
+       SND_BEBOB_DEV_ENTRY(VEN_YAMAHA, 0x0010000b, &yamaha_terratec_spec),
        /* YAMAHA, GO46 */
-       SND_BEBOB_DEV_ENTRY(VEN_YAMAHA, 0x0010000c, &yamaha_go_spec),
+       SND_BEBOB_DEV_ENTRY(VEN_YAMAHA, 0x0010000c, &yamaha_terratec_spec),
        /* Focusrite, SaffirePro 26 I/O */
        SND_BEBOB_DEV_ENTRY(VEN_FOCUSRITE, 0x00000003, &saffirepro_26_spec),
        /* Focusrite, SaffirePro 10 I/O */
index e7f1bb9..175da87 100644 (file)
@@ -235,8 +235,7 @@ int snd_bebob_create_hwdep_device(struct snd_bebob *bebob);
 
 /* model specific operations */
 extern const struct snd_bebob_spec phase88_rack_spec;
-extern const struct snd_bebob_spec phase24_series_spec;
-extern const struct snd_bebob_spec yamaha_go_spec;
+extern const struct snd_bebob_spec yamaha_terratec_spec;
 extern const struct snd_bebob_spec saffirepro_26_spec;
 extern const struct snd_bebob_spec saffirepro_10_spec;
 extern const struct snd_bebob_spec saffire_le_spec;
index c38358b..2fdaf93 100644 (file)
@@ -36,25 +36,6 @@ end:
        return err;
 }
 
-static enum snd_bebob_clock_type phase24_series_clk_src_types[] = {
-       SND_BEBOB_CLOCK_TYPE_INTERNAL,
-       SND_BEBOB_CLOCK_TYPE_EXTERNAL,  /* S/PDIF */
-};
-static int
-phase24_series_clk_src_get(struct snd_bebob *bebob, unsigned int *id)
-{
-       int err;
-
-       err = avc_audio_get_selector(bebob->unit, 0, 4, id);
-       if (err < 0)
-               return err;
-
-       if (*id >= ARRAY_SIZE(phase24_series_clk_src_types))
-               return -EIO;
-
-       return 0;
-}
-
 static const struct snd_bebob_rate_spec phase_series_rate_spec = {
        .get    = &snd_bebob_stream_get_rate,
        .set    = &snd_bebob_stream_set_rate,
@@ -71,15 +52,3 @@ const struct snd_bebob_spec phase88_rack_spec = {
        .rate   = &phase_series_rate_spec,
        .meter  = NULL
 };
-
-/* 'PHASE 24 FW' and 'PHASE X24 FW' */
-static const struct snd_bebob_clock_spec phase24_series_clk = {
-       .num    = ARRAY_SIZE(phase24_series_clk_src_types),
-       .types  = phase24_series_clk_src_types,
-       .get    = &phase24_series_clk_src_get,
-};
-const struct snd_bebob_spec phase24_series_spec = {
-       .clock  = &phase24_series_clk,
-       .rate   = &phase_series_rate_spec,
-       .meter  = NULL
-};
diff --git a/sound/firewire/bebob/bebob_yamaha.c b/sound/firewire/bebob/bebob_yamaha.c
deleted file mode 100644 (file)
index 90d4404..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * bebob_yamaha.c - a part of driver for BeBoB based devices
- *
- * Copyright (c) 2013-2014 Takashi Sakamoto
- *
- * Licensed under the terms of the GNU General Public License, version 2.
- */
-
-#include "./bebob.h"
-
-/*
- * NOTE:
- * Yamaha GO44 is not designed to be used as stand-alone mixer. So any streams
- * must be accompanied. If changing the state, a LED on the device starts to
- * blink and its sync status is false. In this state, the device sounds nothing
- * even if streaming. To start streaming at the current sampling rate is only
- * way to revocer this state. GO46 is better for stand-alone mixer.
- *
- * Both of them have a capability to change its sampling rate up to 192.0kHz.
- * At 192.0kHz, the device reports 4 PCM-in, 1 MIDI-in, 6 PCM-out, 1 MIDI-out.
- * But Yamaha's driver reduce 2 PCM-in, 1 MIDI-in, 2 PCM-out, 1 MIDI-out to use
- * 'Extended Stream Format Information Command - Single Request' in 'Additional
- * AVC commands' defined by BridgeCo.
- * This ALSA driver don't do this because a bit tiresome. Then isochronous
- * streaming with many asynchronous transactions brings sounds with noises.
- * Unfortunately current 'ffado-mixer' generated many asynchronous transaction
- * to observe device's state, mainly check cmp connection and signal format. I
- * reccomend users to close ffado-mixer at 192.0kHz if mixer is needless.
- */
-
-static enum snd_bebob_clock_type clk_src_types[] = {
-       SND_BEBOB_CLOCK_TYPE_INTERNAL,
-       SND_BEBOB_CLOCK_TYPE_EXTERNAL,  /* S/PDIF */
-};
-static int
-clk_src_get(struct snd_bebob *bebob, unsigned int *id)
-{
-       int err;
-
-       err = avc_audio_get_selector(bebob->unit, 0, 4, id);
-       if (err < 0)
-               return err;
-
-       if (*id >= ARRAY_SIZE(clk_src_types))
-               return -EIO;
-
-       return 0;
-}
-static const struct snd_bebob_clock_spec clock_spec = {
-       .num    = ARRAY_SIZE(clk_src_types),
-       .types  = clk_src_types,
-       .get    = &clk_src_get,
-};
-static const struct snd_bebob_rate_spec rate_spec = {
-       .get    = &snd_bebob_stream_get_rate,
-       .set    = &snd_bebob_stream_set_rate,
-};
-const struct snd_bebob_spec yamaha_go_spec = {
-       .clock  = &clock_spec,
-       .rate   = &rate_spec,
-       .meter  = NULL
-};
diff --git a/sound/firewire/bebob/bebob_yamaha_terratec.c b/sound/firewire/bebob/bebob_yamaha_terratec.c
new file mode 100644 (file)
index 0000000..a6be3e7
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * bebob_yamaha.c - a part of driver for BeBoB based devices
+ *
+ * Copyright (c) 2013-2014 Takashi Sakamoto
+ *
+ * Licensed under the terms of the GNU General Public License, version 2.
+ */
+
+#include "./bebob.h"
+
+/*
+ * NOTE:
+ * Yamaha GO44 is not designed to be used as stand-alone mixer. So any streams
+ * must be accompanied. If changing the state, a LED on the device starts to
+ * blink and its sync status is false. In this state, the device sounds nothing
+ * even if streaming. To start streaming at the current sampling rate is only
+ * way to recover this state. GO46 is better for stand-alone mixer.
+ *
+ * Both of them have a capability to change its sampling rate up to 192.0kHz.
+ * At 192.0kHz, the device reports 4 PCM-in, 1 MIDI-in, 6 PCM-out, 1 MIDI-out.
+ * But Yamaha's driver reduce 2 PCM-in, 1 MIDI-in, 2 PCM-out, 1 MIDI-out to use
+ * 'Extended Stream Format Information Command - Single Request' in 'Additional
+ * AVC commands' defined by BridgeCo.
+ * This ALSA driver don't do this because a bit tiresome. Then isochronous
+ * streaming with many asynchronous transactions brings sounds with noises.
+ * Unfortunately current 'ffado-mixer' generated many asynchronous transaction
+ * to observe device's state, mainly check cmp connection and signal format. I
+ * recommend users to close ffado-mixer at 192.0kHz if mixer is needless.
+ *
+ * Terratec PHASE 24 FW and PHASE X24 FW are internally the same as
+ * Yamaha GO 44 and GO 46. Yamaha and Terratec had cooperated for these models.
+ */
+
+static enum snd_bebob_clock_type clk_src_types[] = {
+       SND_BEBOB_CLOCK_TYPE_INTERNAL,
+       SND_BEBOB_CLOCK_TYPE_EXTERNAL,  /* S/PDIF */
+};
+static int
+clk_src_get(struct snd_bebob *bebob, unsigned int *id)
+{
+       int err;
+
+       err = avc_audio_get_selector(bebob->unit, 0, 4, id);
+       if (err < 0)
+               return err;
+
+       if (*id >= ARRAY_SIZE(clk_src_types))
+               return -EIO;
+
+       return 0;
+}
+static const struct snd_bebob_clock_spec clock_spec = {
+       .num    = ARRAY_SIZE(clk_src_types),
+       .types  = clk_src_types,
+       .get    = &clk_src_get,
+};
+static const struct snd_bebob_rate_spec rate_spec = {
+       .get    = &snd_bebob_stream_get_rate,
+       .set    = &snd_bebob_stream_set_rate,
+};
+const struct snd_bebob_spec yamaha_terratec_spec = {
+       .clock  = &clock_spec,
+       .rate   = &rate_spec,
+       .meter  = NULL
+};
index 4aa0249..6074fe1 100644 (file)
@@ -302,7 +302,7 @@ static snd_pcm_uframes_t playback_pointer(struct snd_pcm_substream *substream)
 
 int snd_dice_create_pcm(struct snd_dice *dice)
 {
-       static struct snd_pcm_ops capture_ops = {
+       static const struct snd_pcm_ops capture_ops = {
                .open      = pcm_open,
                .close     = pcm_close,
                .ioctl     = snd_pcm_lib_ioctl,
@@ -314,7 +314,7 @@ int snd_dice_create_pcm(struct snd_dice *dice)
                .page      = snd_pcm_lib_get_vmalloc_page,
                .mmap      = snd_pcm_lib_mmap_vmalloc,
        };
-       static struct snd_pcm_ops playback_ops = {
+       static const struct snd_pcm_ops playback_ops = {
                .open      = pcm_open,
                .close     = pcm_close,
                .ioctl     = snd_pcm_lib_ioctl,
index cac28f7..613f058 100644 (file)
@@ -329,7 +329,7 @@ static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstrm)
        return amdtp_stream_pcm_pointer(&dg00x->rx_stream);
 }
 
-static struct snd_pcm_ops pcm_capture_ops = {
+static const struct snd_pcm_ops pcm_capture_ops = {
        .open           = pcm_open,
        .close          = pcm_close,
        .ioctl          = snd_pcm_lib_ioctl,
@@ -341,7 +341,7 @@ static struct snd_pcm_ops pcm_capture_ops = {
        .page           = snd_pcm_lib_get_vmalloc_page,
 };
 
-static struct snd_pcm_ops pcm_playback_ops = {
+static const struct snd_pcm_ops pcm_playback_ops = {
        .open           = pcm_open,
        .close          = pcm_close,
        .ioctl          = snd_pcm_lib_ioctl,
index 8d23341..f3530f8 100644 (file)
@@ -388,7 +388,7 @@ static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstm)
 
 int snd_oxfw_create_pcm(struct snd_oxfw *oxfw)
 {
-       static struct snd_pcm_ops capture_ops = {
+       static const struct snd_pcm_ops capture_ops = {
                .open      = pcm_open,
                .close     = pcm_close,
                .ioctl     = snd_pcm_lib_ioctl,
@@ -400,7 +400,7 @@ int snd_oxfw_create_pcm(struct snd_oxfw *oxfw)
                .page      = snd_pcm_lib_get_vmalloc_page,
                .mmap      = snd_pcm_lib_mmap_vmalloc,
        };
-       static struct snd_pcm_ops playback_ops = {
+       static const struct snd_pcm_ops playback_ops = {
                .open      = pcm_open,
                .close     = pcm_close,
                .ioctl     = snd_pcm_lib_ioctl,
index 380d3db..79db1b6 100644 (file)
@@ -268,7 +268,7 @@ static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstrm)
        return amdtp_stream_pcm_pointer(&tscm->rx_stream);
 }
 
-static struct snd_pcm_ops pcm_capture_ops = {
+static const struct snd_pcm_ops pcm_capture_ops = {
        .open           = pcm_open,
        .close          = pcm_close,
        .ioctl          = snd_pcm_lib_ioctl,
@@ -280,7 +280,7 @@ static struct snd_pcm_ops pcm_capture_ops = {
        .page           = snd_pcm_lib_get_vmalloc_page,
 };
 
-static struct snd_pcm_ops pcm_playback_ops = {
+static const struct snd_pcm_ops pcm_playback_ops = {
        .open           = pcm_open,
        .close          = pcm_close,
        .ioctl          = snd_pcm_lib_ioctl,
index 2441273..3be051a 100644 (file)
@@ -424,7 +424,7 @@ void snd_hdac_ext_stream_spbcap_enable(struct hdac_ext_bus *ebus,
        struct hdac_bus *bus = &ebus->bus;
 
        if (!bus->spbcap) {
-               dev_err(bus->dev, "Address of SPB capability is NULL");
+               dev_err(bus->dev, "Address of SPB capability is NULL\n");
                return;
        }
 
@@ -453,7 +453,7 @@ int snd_hdac_ext_stream_set_spib(struct hdac_ext_bus *ebus,
        struct hdac_bus *bus = &ebus->bus;
 
        if (!bus->spbcap) {
-               dev_err(bus->dev, "Address of SPB capability is NULL");
+               dev_err(bus->dev, "Address of SPB capability is NULL\n");
                return -EINVAL;
        }
 
@@ -476,7 +476,7 @@ int snd_hdac_ext_stream_get_spbmaxfifo(struct hdac_ext_bus *ebus,
        struct hdac_bus *bus = &ebus->bus;
 
        if (!bus->spbcap) {
-               dev_err(bus->dev, "Address of SPB capability is NULL");
+               dev_err(bus->dev, "Address of SPB capability is NULL\n");
                return -EINVAL;
        }
 
@@ -516,7 +516,7 @@ void snd_hdac_ext_stream_drsm_enable(struct hdac_ext_bus *ebus,
        struct hdac_bus *bus = &ebus->bus;
 
        if (!bus->drsmcap) {
-               dev_err(bus->dev, "Address of DRSM capability is NULL");
+               dev_err(bus->dev, "Address of DRSM capability is NULL\n");
                return;
        }
 
@@ -545,7 +545,7 @@ int snd_hdac_ext_stream_set_dpibr(struct hdac_ext_bus *ebus,
        struct hdac_bus *bus = &ebus->bus;
 
        if (!bus->drsmcap) {
-               dev_err(bus->dev, "Address of DRSM capability is NULL");
+               dev_err(bus->dev, "Address of DRSM capability is NULL\n");
                return -EINVAL;
        }
 
index 1fc6d8b..8c36990 100644 (file)
@@ -571,7 +571,7 @@ snd_ad1889_capture_pointer(struct snd_pcm_substream *ss)
        return bytes_to_frames(ss->runtime, ptr);
 }
 
-static struct snd_pcm_ops snd_ad1889_playback_ops = {
+static const struct snd_pcm_ops snd_ad1889_playback_ops = {
        .open = snd_ad1889_playback_open,
        .close = snd_ad1889_playback_close,
        .ioctl = snd_pcm_lib_ioctl,
@@ -582,7 +582,7 @@ static struct snd_pcm_ops snd_ad1889_playback_ops = {
        .pointer = snd_ad1889_playback_pointer, 
 };
 
-static struct snd_pcm_ops snd_ad1889_capture_ops = {
+static const struct snd_pcm_ops snd_ad1889_capture_ops = {
        .open = snd_ad1889_capture_open,
        .close = snd_ad1889_capture_close,
        .ioctl = snd_pcm_lib_ioctl,
index 36470af..92b819e 100644 (file)
@@ -1408,6 +1408,7 @@ snd_ali_playback_pointer(struct snd_pcm_substream *substream)
        spin_unlock(&codec->reg_lock);
        dev_dbg(codec->card->dev, "playback pointer returned cso=%xh.\n", cso);
 
+       cso %= runtime->buffer_size;
        return cso;
 }
 
@@ -1428,6 +1429,7 @@ static snd_pcm_uframes_t snd_ali_pointer(struct snd_pcm_substream *substream)
        cso = inw(ALI_REG(codec, ALI_CSO_ALPHA_FMS + 2));
        spin_unlock(&codec->reg_lock);
 
+       cso %= runtime->buffer_size;
        return cso;
 }
 
index add3176..ab75601 100644 (file)
@@ -563,7 +563,7 @@ static snd_pcm_uframes_t snd_als300_pointer(struct snd_pcm_substream *substream)
        return bytes_to_frames(substream->runtime, current_ptr);
 }
 
-static struct snd_pcm_ops snd_als300_playback_ops = {
+static const struct snd_pcm_ops snd_als300_playback_ops = {
        .open =         snd_als300_playback_open,
        .close =        snd_als300_playback_close,
        .ioctl =        snd_pcm_lib_ioctl,
@@ -574,7 +574,7 @@ static struct snd_pcm_ops snd_als300_playback_ops = {
        .pointer =      snd_als300_pointer,
 };
 
-static struct snd_pcm_ops snd_als300_capture_ops = {
+static const struct snd_pcm_ops snd_als300_capture_ops = {
        .open =         snd_als300_capture_open,
        .close =        snd_als300_capture_close,
        .ioctl =        snd_pcm_lib_ioctl,
index ff39a0c..edabe13 100644 (file)
@@ -672,7 +672,7 @@ static int snd_als4000_capture_close(struct snd_pcm_substream *substream)
 
 /******************************************************************/
 
-static struct snd_pcm_ops snd_als4000_playback_ops = {
+static const struct snd_pcm_ops snd_als4000_playback_ops = {
        .open =         snd_als4000_playback_open,
        .close =        snd_als4000_playback_close,
        .ioctl =        snd_pcm_lib_ioctl,
@@ -683,7 +683,7 @@ static struct snd_pcm_ops snd_als4000_playback_ops = {
        .pointer =      snd_als4000_playback_pointer
 };
 
-static struct snd_pcm_ops snd_als4000_capture_ops = {
+static const struct snd_pcm_ops snd_als4000_capture_ops = {
        .open =         snd_als4000_capture_open,
        .close =        snd_als4000_capture_close,
        .ioctl =        snd_pcm_lib_ioctl,
index 1039ecc..976a3d2 100644 (file)
@@ -1138,7 +1138,7 @@ static int snd_card_asihpi_playback_close(struct snd_pcm_substream *substream)
        return 0;
 }
 
-static struct snd_pcm_ops snd_card_asihpi_playback_mmap_ops = {
+static const struct snd_pcm_ops snd_card_asihpi_playback_mmap_ops = {
        .open = snd_card_asihpi_playback_open,
        .close = snd_card_asihpi_playback_close,
        .ioctl = snd_card_asihpi_playback_ioctl,
@@ -1305,7 +1305,7 @@ static int snd_card_asihpi_capture_close(struct snd_pcm_substream *substream)
        return 0;
 }
 
-static struct snd_pcm_ops snd_card_asihpi_capture_mmap_ops = {
+static const struct snd_pcm_ops snd_card_asihpi_capture_mmap_ops = {
        .open = snd_card_asihpi_capture_open,
        .close = snd_card_asihpi_capture_close,
        .ioctl = snd_card_asihpi_capture_ioctl,
index 510e56c..f9b5764 100644 (file)
@@ -2323,11 +2323,8 @@ u16 hpi_sample_clock_get_source_index(u32 h_control, u16 *pw_source_index)
 u16 hpi_sample_clock_query_local_rate(const u32 h_clock, const u32 index,
        u32 *prate)
 {
-       u16 err;
-       err = hpi_control_query(h_clock, HPI_SAMPLECLOCK_LOCAL_SAMPLERATE,
-               index, 0, prate);
-
-       return err;
+       return hpi_control_query(h_clock, HPI_SAMPLECLOCK_LOCAL_SAMPLERATE,
+                                index, 0, prate);
 }
 
 u16 hpi_sample_clock_set_local_rate(u32 h_control, u32 sample_rate)
index 2ce0022..a40c918 100644 (file)
@@ -1148,7 +1148,7 @@ static int snd_atiixp_spdif_close(struct snd_pcm_substream *substream)
 }
 
 /* AC97 playback */
-static struct snd_pcm_ops snd_atiixp_playback_ops = {
+static const struct snd_pcm_ops snd_atiixp_playback_ops = {
        .open =         snd_atiixp_playback_open,
        .close =        snd_atiixp_playback_close,
        .ioctl =        snd_pcm_lib_ioctl,
@@ -1160,7 +1160,7 @@ static struct snd_pcm_ops snd_atiixp_playback_ops = {
 };
 
 /* AC97 capture */
-static struct snd_pcm_ops snd_atiixp_capture_ops = {
+static const struct snd_pcm_ops snd_atiixp_capture_ops = {
        .open =         snd_atiixp_capture_open,
        .close =        snd_atiixp_capture_close,
        .ioctl =        snd_pcm_lib_ioctl,
@@ -1172,7 +1172,7 @@ static struct snd_pcm_ops snd_atiixp_capture_ops = {
 };
 
 /* SPDIF playback */
-static struct snd_pcm_ops snd_atiixp_spdif_ops = {
+static const struct snd_pcm_ops snd_atiixp_spdif_ops = {
        .open =         snd_atiixp_spdif_open,
        .close =        snd_atiixp_spdif_close,
        .ioctl =        snd_pcm_lib_ioctl,
index c534552..40152fe 100644 (file)
@@ -947,7 +947,7 @@ static int snd_atiixp_capture_close(struct snd_pcm_substream *substream)
 
 
 /* AC97 playback */
-static struct snd_pcm_ops snd_atiixp_playback_ops = {
+static const struct snd_pcm_ops snd_atiixp_playback_ops = {
        .open =         snd_atiixp_playback_open,
        .close =        snd_atiixp_playback_close,
        .ioctl =        snd_pcm_lib_ioctl,
@@ -959,7 +959,7 @@ static struct snd_pcm_ops snd_atiixp_playback_ops = {
 };
 
 /* AC97 capture */
-static struct snd_pcm_ops snd_atiixp_capture_ops = {
+static const struct snd_pcm_ops snd_atiixp_capture_ops = {
        .open =         snd_atiixp_capture_open,
        .close =        snd_atiixp_capture_close,
        .ioctl =        snd_pcm_lib_ioctl,
index d3125c1..e1af24f 100644 (file)
@@ -1043,7 +1043,7 @@ static void vortex_fifo_init(vortex_t * vortex)
        for (x = NR_ADB - 1; x >= 0; x--) {
                hwwrite(vortex->mmio, addr, (FIFO_U0 | FIFO_U1));
                if (hwread(vortex->mmio, addr) != (FIFO_U0 | FIFO_U1))
-                       dev_err(vortex->card->dev, "bad adb fifo reset!");
+                       dev_err(vortex->card->dev, "bad adb fifo reset!\n");
                vortex_fifo_clearadbdata(vortex, x, FIFO_SIZE);
                addr -= 4;
        }
index 1677143..57bbb87 100644 (file)
@@ -179,7 +179,7 @@ static struct pci_driver aw2_driver = {
 module_pci_driver(aw2_driver);
 
 /* operators for playback PCM alsa interface */
-static struct snd_pcm_ops snd_aw2_playback_ops = {
+static const struct snd_pcm_ops snd_aw2_playback_ops = {
        .open = snd_aw2_pcm_playback_open,
        .close = snd_aw2_pcm_playback_close,
        .ioctl = snd_pcm_lib_ioctl,
@@ -191,7 +191,7 @@ static struct snd_pcm_ops snd_aw2_playback_ops = {
 };
 
 /* operators for capture PCM alsa interface */
-static struct snd_pcm_ops snd_aw2_capture_ops = {
+static const struct snd_pcm_ops snd_aw2_capture_ops = {
        .open = snd_aw2_pcm_capture_open,
        .close = snd_aw2_pcm_capture_close,
        .ioctl = snd_pcm_lib_ioctl,
index 5e2ef0b..80c4a44 100644 (file)
@@ -2090,7 +2090,7 @@ snd_azf3328_pcm_close(struct snd_pcm_substream *substream
 
 /******************************************************************/
 
-static struct snd_pcm_ops snd_azf3328_playback_ops = {
+static const struct snd_pcm_ops snd_azf3328_playback_ops = {
        .open =         snd_azf3328_pcm_playback_open,
        .close =        snd_azf3328_pcm_close,
        .ioctl =        snd_pcm_lib_ioctl,
@@ -2101,7 +2101,7 @@ static struct snd_pcm_ops snd_azf3328_playback_ops = {
        .pointer =      snd_azf3328_pcm_pointer
 };
 
-static struct snd_pcm_ops snd_azf3328_capture_ops = {
+static const struct snd_pcm_ops snd_azf3328_capture_ops = {
        .open =         snd_azf3328_pcm_capture_open,
        .close =        snd_azf3328_pcm_close,
        .ioctl =        snd_pcm_lib_ioctl,
@@ -2112,7 +2112,7 @@ static struct snd_pcm_ops snd_azf3328_capture_ops = {
        .pointer =      snd_azf3328_pcm_pointer
 };
 
-static struct snd_pcm_ops snd_azf3328_i2s_out_ops = {
+static const struct snd_pcm_ops snd_azf3328_i2s_out_ops = {
        .open =         snd_azf3328_pcm_i2s_out_open,
        .close =        snd_azf3328_pcm_close,
        .ioctl =        snd_pcm_lib_ioctl,
index 5925b71..f2c0709 100644 (file)
@@ -550,7 +550,7 @@ static snd_pcm_uframes_t snd_bt87x_pointer(struct snd_pcm_substream *substream)
        return (snd_pcm_uframes_t)bytes_to_frames(runtime, chip->current_line * chip->line_bytes);
 }
 
-static struct snd_pcm_ops snd_bt87x_pcm_ops = {
+static const struct snd_pcm_ops snd_bt87x_pcm_ops = {
        .open = snd_bt87x_pcm_open,
        .close = snd_bt87x_close,
        .ioctl = snd_pcm_lib_ioctl,
index d3cd956..6165a57 100644 (file)
@@ -1109,7 +1109,7 @@ snd_ca0106_pcm_pointer_capture(struct snd_pcm_substream *substream)
 }
 
 /* operators */
-static struct snd_pcm_ops snd_ca0106_playback_front_ops = {
+static const struct snd_pcm_ops snd_ca0106_playback_front_ops = {
        .open =        snd_ca0106_pcm_open_playback_front,
        .close =       snd_ca0106_pcm_close_playback,
        .ioctl =       snd_pcm_lib_ioctl,
@@ -1120,7 +1120,7 @@ static struct snd_pcm_ops snd_ca0106_playback_front_ops = {
        .pointer =     snd_ca0106_pcm_pointer_playback,
 };
 
-static struct snd_pcm_ops snd_ca0106_capture_0_ops = {
+static const struct snd_pcm_ops snd_ca0106_capture_0_ops = {
        .open =        snd_ca0106_pcm_open_0_capture,
        .close =       snd_ca0106_pcm_close_capture,
        .ioctl =       snd_pcm_lib_ioctl,
@@ -1131,7 +1131,7 @@ static struct snd_pcm_ops snd_ca0106_capture_0_ops = {
        .pointer =     snd_ca0106_pcm_pointer_capture,
 };
 
-static struct snd_pcm_ops snd_ca0106_capture_1_ops = {
+static const struct snd_pcm_ops snd_ca0106_capture_1_ops = {
        .open =        snd_ca0106_pcm_open_1_capture,
        .close =       snd_ca0106_pcm_close_capture,
        .ioctl =       snd_pcm_lib_ioctl,
@@ -1142,7 +1142,7 @@ static struct snd_pcm_ops snd_ca0106_capture_1_ops = {
        .pointer =     snd_ca0106_pcm_pointer_capture,
 };
 
-static struct snd_pcm_ops snd_ca0106_capture_2_ops = {
+static const struct snd_pcm_ops snd_ca0106_capture_2_ops = {
        .open =        snd_ca0106_pcm_open_2_capture,
        .close =       snd_ca0106_pcm_close_capture,
        .ioctl =       snd_pcm_lib_ioctl,
@@ -1153,7 +1153,7 @@ static struct snd_pcm_ops snd_ca0106_capture_2_ops = {
        .pointer =     snd_ca0106_pcm_pointer_capture,
 };
 
-static struct snd_pcm_ops snd_ca0106_capture_3_ops = {
+static const struct snd_pcm_ops snd_ca0106_capture_3_ops = {
        .open =        snd_ca0106_pcm_open_3_capture,
        .close =       snd_ca0106_pcm_close_capture,
        .ioctl =       snd_pcm_lib_ioctl,
@@ -1164,7 +1164,7 @@ static struct snd_pcm_ops snd_ca0106_capture_3_ops = {
        .pointer =     snd_ca0106_pcm_pointer_capture,
 };
 
-static struct snd_pcm_ops snd_ca0106_playback_center_lfe_ops = {
+static const struct snd_pcm_ops snd_ca0106_playback_center_lfe_ops = {
         .open =         snd_ca0106_pcm_open_playback_center_lfe,
         .close =        snd_ca0106_pcm_close_playback,
         .ioctl =        snd_pcm_lib_ioctl,
@@ -1175,7 +1175,7 @@ static struct snd_pcm_ops snd_ca0106_playback_center_lfe_ops = {
         .pointer =      snd_ca0106_pcm_pointer_playback, 
 };
 
-static struct snd_pcm_ops snd_ca0106_playback_unknown_ops = {
+static const struct snd_pcm_ops snd_ca0106_playback_unknown_ops = {
         .open =         snd_ca0106_pcm_open_playback_unknown,
         .close =        snd_ca0106_pcm_close_playback,
         .ioctl =        snd_pcm_lib_ioctl,
@@ -1186,7 +1186,7 @@ static struct snd_pcm_ops snd_ca0106_playback_unknown_ops = {
         .pointer =      snd_ca0106_pcm_pointer_playback, 
 };
 
-static struct snd_pcm_ops snd_ca0106_playback_rear_ops = {
+static const struct snd_pcm_ops snd_ca0106_playback_rear_ops = {
         .open =         snd_ca0106_pcm_open_playback_rear,
         .close =        snd_ca0106_pcm_close_playback,
         .ioctl =        snd_pcm_lib_ioctl,
index 24cdcba..73f5935 100644 (file)
@@ -1838,7 +1838,7 @@ static int snd_cmipci_capture_spdif_close(struct snd_pcm_substream *substream)
 /*
  */
 
-static struct snd_pcm_ops snd_cmipci_playback_ops = {
+static const struct snd_pcm_ops snd_cmipci_playback_ops = {
        .open =         snd_cmipci_playback_open,
        .close =        snd_cmipci_playback_close,
        .ioctl =        snd_pcm_lib_ioctl,
@@ -1849,7 +1849,7 @@ static struct snd_pcm_ops snd_cmipci_playback_ops = {
        .pointer =      snd_cmipci_playback_pointer,
 };
 
-static struct snd_pcm_ops snd_cmipci_capture_ops = {
+static const struct snd_pcm_ops snd_cmipci_capture_ops = {
        .open =         snd_cmipci_capture_open,
        .close =        snd_cmipci_capture_close,
        .ioctl =        snd_pcm_lib_ioctl,
@@ -1860,7 +1860,7 @@ static struct snd_pcm_ops snd_cmipci_capture_ops = {
        .pointer =      snd_cmipci_capture_pointer,
 };
 
-static struct snd_pcm_ops snd_cmipci_playback2_ops = {
+static const struct snd_pcm_ops snd_cmipci_playback2_ops = {
        .open =         snd_cmipci_playback2_open,
        .close =        snd_cmipci_playback2_close,
        .ioctl =        snd_pcm_lib_ioctl,
@@ -1871,7 +1871,7 @@ static struct snd_pcm_ops snd_cmipci_playback2_ops = {
        .pointer =      snd_cmipci_capture_pointer,     /* channel B */
 };
 
-static struct snd_pcm_ops snd_cmipci_playback_spdif_ops = {
+static const struct snd_pcm_ops snd_cmipci_playback_spdif_ops = {
        .open =         snd_cmipci_playback_spdif_open,
        .close =        snd_cmipci_playback_spdif_close,
        .ioctl =        snd_pcm_lib_ioctl,
@@ -1882,7 +1882,7 @@ static struct snd_pcm_ops snd_cmipci_playback_spdif_ops = {
        .pointer =      snd_cmipci_playback_pointer,
 };
 
-static struct snd_pcm_ops snd_cmipci_capture_spdif_ops = {
+static const struct snd_pcm_ops snd_cmipci_capture_spdif_ops = {
        .open =         snd_cmipci_capture_spdif_open,
        .close =        snd_cmipci_capture_spdif_close,
        .ioctl =        snd_pcm_lib_ioctl,
index c296fd0..615d8a9 100644 (file)
@@ -951,7 +951,7 @@ static int snd_cs4281_capture_close(struct snd_pcm_substream *substream)
        return 0;
 }
 
-static struct snd_pcm_ops snd_cs4281_playback_ops = {
+static const struct snd_pcm_ops snd_cs4281_playback_ops = {
        .open =         snd_cs4281_playback_open,
        .close =        snd_cs4281_playback_close,
        .ioctl =        snd_pcm_lib_ioctl,
@@ -962,7 +962,7 @@ static struct snd_pcm_ops snd_cs4281_playback_ops = {
        .pointer =      snd_cs4281_pointer,
 };
 
-static struct snd_pcm_ops snd_cs4281_capture_ops = {
+static const struct snd_pcm_ops snd_cs4281_capture_ops = {
        .open =         snd_cs4281_capture_open,
        .close =        snd_cs4281_capture_close,
        .ioctl =        snd_pcm_lib_ioctl,
index 2706f27..528102c 100644 (file)
@@ -2460,7 +2460,7 @@ static int cs46xx_detect_codec(struct snd_cs46xx *chip, int codec)
                udelay(10);
                if (snd_cs46xx_codec_read(chip, AC97_RESET, codec) & 0x8000) {
                        dev_dbg(chip->card->dev,
-                               "seconadry codec not present\n");
+                               "secondary codec not present\n");
                        return -ENXIO;
                }
        }
@@ -2503,7 +2503,7 @@ int snd_cs46xx_mixer(struct snd_cs46xx *chip, int spdif_device)
        chip->nr_ac97_codecs = 1;
 
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
-       dev_dbg(chip->card->dev, "detecting seconadry codec\n");
+       dev_dbg(chip->card->dev, "detecting secondary codec\n");
        /* try detect a secondary codec */
        if (! cs46xx_detect_codec(chip, CS46XX_SECONDARY_CODEC_INDEX))
                chip->nr_ac97_codecs = 2;
index d2951ed..4a0cbd2 100644 (file)
@@ -1441,7 +1441,7 @@ int cs46xx_dsp_scb_and_task_init (struct snd_cs46xx *chip)
        
        if (chip->nr_ac97_codecs == 2) {
                /* create CODEC tasklet for rear Center/LFE output 
-                  slot 6 and 9 on seconadry CODEC */
+                  slot 6 and 9 on secondary CODEC */
                clfe_codec_out_scb = cs46xx_dsp_create_codec_out_scb(chip,"CodecOutSCB_CLFE",0x0030,0x0030,
                                                                     CLFE_MIXER_SCB_ADDR,
                                                                     CLFE_CODEC_SCB_ADDR,
index 27fa57d..c208c1d 100644 (file)
@@ -380,7 +380,7 @@ static int snd_cs5535audio_capture_prepare(struct snd_pcm_substream *substream)
                                 substream->runtime->rate);
 }
 
-static struct snd_pcm_ops snd_cs5535audio_playback_ops = {
+static const struct snd_pcm_ops snd_cs5535audio_playback_ops = {
        .open =         snd_cs5535audio_playback_open,
        .close =        snd_cs5535audio_playback_close,
        .ioctl =        snd_pcm_lib_ioctl,
@@ -391,7 +391,7 @@ static struct snd_pcm_ops snd_cs5535audio_playback_ops = {
        .pointer =      snd_cs5535audio_pcm_pointer,
 };
 
-static struct snd_pcm_ops snd_cs5535audio_capture_ops = {
+static const struct snd_pcm_ops snd_cs5535audio_capture_ops = {
        .open =         snd_cs5535audio_capture_open,
        .close =        snd_cs5535audio_capture_close,
        .ioctl =        snd_pcm_lib_ioctl,
index 977a598..908658a 100644 (file)
@@ -1623,7 +1623,7 @@ static int atc_resume(struct ct_atc *atc)
 }
 #endif
 
-static struct ct_atc atc_preset = {
+static const struct ct_atc atc_preset = {
        .map_audio_buffer = ct_map_audio_buffer,
        .unmap_audio_buffer = ct_unmap_audio_buffer,
        .pcm_playback_prepare = atc_pcm_playback_prepare,
index d86c474..9749780 100644 (file)
@@ -372,7 +372,7 @@ ct_pcm_capture_pointer(struct snd_pcm_substream *substream)
 }
 
 /* PCM operators for playback */
-static struct snd_pcm_ops ct_pcm_playback_ops = {
+static const struct snd_pcm_ops ct_pcm_playback_ops = {
        .open           = ct_pcm_playback_open,
        .close          = ct_pcm_playback_close,
        .ioctl          = snd_pcm_lib_ioctl,
@@ -385,7 +385,7 @@ static struct snd_pcm_ops ct_pcm_playback_ops = {
 };
 
 /* PCM operators for capture */
-static struct snd_pcm_ops ct_pcm_capture_ops = {
+static const struct snd_pcm_ops ct_pcm_capture_ops = {
        .open           = ct_pcm_capture_open,
        .close          = ct_pcm_capture_close,
        .ioctl          = snd_pcm_lib_ioctl,
index 419306e..520e19b 100644 (file)
@@ -166,11 +166,7 @@ static void ct_vm_unmap(struct ct_vm *vm, struct ct_vm_block *block)
 static dma_addr_t
 ct_get_ptp_phys(struct ct_vm *vm, int index)
 {
-       dma_addr_t addr;
-
-       addr = (index >= CT_PTP_NUM) ? ~0UL : vm->ptp[index].addr;
-
-       return addr;
+       return (index >= CT_PTP_NUM) ? ~0UL : vm->ptp[index].addr;
 }
 
 int ct_vm_create(struct ct_vm **rvm, struct pci_dev *pci)
index 6d1b98d..921037e 100644 (file)
@@ -548,7 +548,7 @@ snd_emu10k1x_pcm_pointer(struct snd_pcm_substream *substream)
 }
 
 /* operators */
-static struct snd_pcm_ops snd_emu10k1x_playback_ops = {
+static const struct snd_pcm_ops snd_emu10k1x_playback_ops = {
        .open =        snd_emu10k1x_playback_open,
        .close =       snd_emu10k1x_playback_close,
        .ioctl =       snd_pcm_lib_ioctl,
@@ -694,7 +694,7 @@ snd_emu10k1x_pcm_pointer_capture(struct snd_pcm_substream *substream)
        return ptr;
 }
 
-static struct snd_pcm_ops snd_emu10k1x_capture_ops = {
+static const struct snd_pcm_ops snd_emu10k1x_capture_ops = {
        .open =        snd_emu10k1x_pcm_open_capture,
        .close =       snd_emu10k1x_pcm_close_capture,
        .ioctl =       snd_pcm_lib_ioctl,
index 14a305b..37be1e1 100644 (file)
@@ -1364,7 +1364,7 @@ static int snd_emu10k1_capture_efx_close(struct snd_pcm_substream *substream)
        return 0;
 }
 
-static struct snd_pcm_ops snd_emu10k1_playback_ops = {
+static const struct snd_pcm_ops snd_emu10k1_playback_ops = {
        .open =                 snd_emu10k1_playback_open,
        .close =                snd_emu10k1_playback_close,
        .ioctl =                snd_pcm_lib_ioctl,
@@ -1376,7 +1376,7 @@ static struct snd_pcm_ops snd_emu10k1_playback_ops = {
        .page =                 snd_pcm_sgbuf_ops_page,
 };
 
-static struct snd_pcm_ops snd_emu10k1_capture_ops = {
+static const struct snd_pcm_ops snd_emu10k1_capture_ops = {
        .open =                 snd_emu10k1_capture_open,
        .close =                snd_emu10k1_capture_close,
        .ioctl =                snd_pcm_lib_ioctl,
@@ -1388,7 +1388,7 @@ static struct snd_pcm_ops snd_emu10k1_capture_ops = {
 };
 
 /* EFX playback */
-static struct snd_pcm_ops snd_emu10k1_efx_playback_ops = {
+static const struct snd_pcm_ops snd_emu10k1_efx_playback_ops = {
        .open =                 snd_emu10k1_efx_playback_open,
        .close =                snd_emu10k1_efx_playback_close,
        .ioctl =                snd_pcm_lib_ioctl,
@@ -1455,7 +1455,7 @@ int snd_emu10k1_pcm_multi(struct snd_emu10k1 *emu, int device)
 }
 
 
-static struct snd_pcm_ops snd_emu10k1_capture_mic_ops = {
+static const struct snd_pcm_ops snd_emu10k1_capture_mic_ops = {
        .open =                 snd_emu10k1_capture_mic_open,
        .close =                snd_emu10k1_capture_mic_close,
        .ioctl =                snd_pcm_lib_ioctl,
@@ -1550,7 +1550,7 @@ static struct snd_kcontrol_new snd_emu10k1_pcm_efx_voices_mask = {
        .put = snd_emu10k1_pcm_efx_voices_mask_put
 };
 
-static struct snd_pcm_ops snd_emu10k1_capture_efx_ops = {
+static const struct snd_pcm_ops snd_emu10k1_capture_efx_ops = {
        .open =                 snd_emu10k1_capture_efx_open,
        .close =                snd_emu10k1_capture_efx_close,
        .ioctl =                snd_pcm_lib_ioctl,
@@ -1791,7 +1791,7 @@ static int snd_emu10k1_fx8010_playback_close(struct snd_pcm_substream *substream
        return 0;
 }
 
-static struct snd_pcm_ops snd_emu10k1_fx8010_playback_ops = {
+static const struct snd_pcm_ops snd_emu10k1_fx8010_playback_ops = {
        .open =                 snd_emu10k1_fx8010_playback_open,
        .close =                snd_emu10k1_fx8010_playback_close,
        .ioctl =                snd_pcm_lib_ioctl,
index 3c60b43..c11f1a2 100644 (file)
@@ -300,37 +300,29 @@ static int snd_p16v_pcm_open_capture(struct snd_pcm_substream *substream)
 static int snd_p16v_pcm_hw_params_playback(struct snd_pcm_substream *substream,
                                      struct snd_pcm_hw_params *hw_params)
 {
-       int result;
-       result = snd_pcm_lib_malloc_pages(substream,
+       return snd_pcm_lib_malloc_pages(substream,
                                        params_buffer_bytes(hw_params));
-       return result;
 }
 
 /* hw_params callback */
 static int snd_p16v_pcm_hw_params_capture(struct snd_pcm_substream *substream,
                                      struct snd_pcm_hw_params *hw_params)
 {
-       int result;
-       result = snd_pcm_lib_malloc_pages(substream,
+       return snd_pcm_lib_malloc_pages(substream,
                                        params_buffer_bytes(hw_params));
-       return result;
 }
 
 
 /* hw_free callback */
 static int snd_p16v_pcm_hw_free_playback(struct snd_pcm_substream *substream)
 {
-       int result;
-       result = snd_pcm_lib_free_pages(substream);
-       return result;
+       return snd_pcm_lib_free_pages(substream);
 }
 
 /* hw_free callback */
 static int snd_p16v_pcm_hw_free_capture(struct snd_pcm_substream *substream)
 {
-       int result;
-       result = snd_pcm_lib_free_pages(substream);
-       return result;
+       return snd_pcm_lib_free_pages(substream);
 }
 
 
@@ -601,7 +593,7 @@ snd_p16v_pcm_pointer_capture(struct snd_pcm_substream *substream)
 }
 
 /* operators */
-static struct snd_pcm_ops snd_p16v_playback_front_ops = {
+static const struct snd_pcm_ops snd_p16v_playback_front_ops = {
        .open =        snd_p16v_pcm_open_playback_front,
        .close =       snd_p16v_pcm_close_playback,
        .ioctl =       snd_pcm_lib_ioctl,
@@ -612,7 +604,7 @@ static struct snd_pcm_ops snd_p16v_playback_front_ops = {
        .pointer =     snd_p16v_pcm_pointer_playback,
 };
 
-static struct snd_pcm_ops snd_p16v_capture_ops = {
+static const struct snd_pcm_ops snd_p16v_capture_ops = {
        .open =        snd_p16v_pcm_open_capture,
        .close =       snd_p16v_pcm_close_capture,
        .ioctl =       snd_pcm_lib_ioctl,
index 626cd21..7e760fe 100644 (file)
@@ -1227,7 +1227,7 @@ static int snd_ensoniq_capture_close(struct snd_pcm_substream *substream)
        return 0;
 }
 
-static struct snd_pcm_ops snd_ensoniq_playback1_ops = {
+static const struct snd_pcm_ops snd_ensoniq_playback1_ops = {
        .open =         snd_ensoniq_playback1_open,
        .close =        snd_ensoniq_playback1_close,
        .ioctl =        snd_pcm_lib_ioctl,
@@ -1238,7 +1238,7 @@ static struct snd_pcm_ops snd_ensoniq_playback1_ops = {
        .pointer =      snd_ensoniq_playback1_pointer,
 };
 
-static struct snd_pcm_ops snd_ensoniq_playback2_ops = {
+static const struct snd_pcm_ops snd_ensoniq_playback2_ops = {
        .open =         snd_ensoniq_playback2_open,
        .close =        snd_ensoniq_playback2_close,
        .ioctl =        snd_pcm_lib_ioctl,
@@ -1249,7 +1249,7 @@ static struct snd_pcm_ops snd_ensoniq_playback2_ops = {
        .pointer =      snd_ensoniq_playback2_pointer,
 };
 
-static struct snd_pcm_ops snd_ensoniq_capture_ops = {
+static const struct snd_pcm_ops snd_ensoniq_capture_ops = {
        .open =         snd_ensoniq_capture_open,
        .close =        snd_ensoniq_capture_close,
        .ioctl =        snd_pcm_lib_ioctl,
index 8963d76..6813558 100644 (file)
@@ -992,7 +992,7 @@ static int snd_es1938_playback_close(struct snd_pcm_substream *substream)
        return 0;
 }
 
-static struct snd_pcm_ops snd_es1938_playback_ops = {
+static const struct snd_pcm_ops snd_es1938_playback_ops = {
        .open =         snd_es1938_playback_open,
        .close =        snd_es1938_playback_close,
        .ioctl =        snd_pcm_lib_ioctl,
@@ -1003,7 +1003,7 @@ static struct snd_pcm_ops snd_es1938_playback_ops = {
        .pointer =      snd_es1938_playback_pointer,
 };
 
-static struct snd_pcm_ops snd_es1938_capture_ops = {
+static const struct snd_pcm_ops snd_es1938_capture_ops = {
        .open =         snd_es1938_capture_open,
        .close =        snd_es1938_capture_close,
        .ioctl =        snd_pcm_lib_ioctl,
index 514f260..8146fb7 100644 (file)
@@ -1677,7 +1677,7 @@ static int snd_es1968_capture_close(struct snd_pcm_substream *substream)
        return 0;
 }
 
-static struct snd_pcm_ops snd_es1968_playback_ops = {
+static const struct snd_pcm_ops snd_es1968_playback_ops = {
        .open =         snd_es1968_playback_open,
        .close =        snd_es1968_playback_close,
        .ioctl =        snd_pcm_lib_ioctl,
@@ -1688,7 +1688,7 @@ static struct snd_pcm_ops snd_es1968_playback_ops = {
        .pointer =      snd_es1968_pcm_pointer,
 };
 
-static struct snd_pcm_ops snd_es1968_capture_ops = {
+static const struct snd_pcm_ops snd_es1968_capture_ops = {
        .open =         snd_es1968_capture_open,
        .close =        snd_es1968_capture_close,
        .ioctl =        snd_pcm_lib_ioctl,
index bade9b9..c47287d 100644 (file)
@@ -691,7 +691,7 @@ static int snd_fm801_capture_close(struct snd_pcm_substream *substream)
        return 0;
 }
 
-static struct snd_pcm_ops snd_fm801_playback_ops = {
+static const struct snd_pcm_ops snd_fm801_playback_ops = {
        .open =         snd_fm801_playback_open,
        .close =        snd_fm801_playback_close,
        .ioctl =        snd_pcm_lib_ioctl,
@@ -702,7 +702,7 @@ static struct snd_pcm_ops snd_fm801_playback_ops = {
        .pointer =      snd_fm801_playback_pointer,
 };
 
-static struct snd_pcm_ops snd_fm801_capture_ops = {
+static const struct snd_pcm_ops snd_fm801_capture_ops = {
        .open =         snd_fm801_capture_open,
        .close =        snd_fm801_capture_close,
        .ioctl =        snd_pcm_lib_ioctl,
index 2ad3b44..5008785 100644 (file)
@@ -696,7 +696,7 @@ static int azx_pcm_mmap(struct snd_pcm_substream *substream,
        return snd_pcm_lib_default_mmap(substream, area);
 }
 
-static struct snd_pcm_ops azx_pcm_ops = {
+static const struct snd_pcm_ops azx_pcm_ops = {
        .open = azx_pcm_open,
        .close = azx_pcm_close,
        .ioctl = snd_pcm_lib_ioctl,
index 9ceb2bc..ad06866 100644 (file)
@@ -4018,7 +4018,7 @@ static int ca0132_build_controls(struct hda_codec *codec)
 /*
  * PCM
  */
-static struct hda_pcm_stream ca0132_pcm_analog_playback = {
+static const struct hda_pcm_stream ca0132_pcm_analog_playback = {
        .substreams = 1,
        .channels_min = 2,
        .channels_max = 6,
@@ -4029,7 +4029,7 @@ static struct hda_pcm_stream ca0132_pcm_analog_playback = {
        },
 };
 
-static struct hda_pcm_stream ca0132_pcm_analog_capture = {
+static const struct hda_pcm_stream ca0132_pcm_analog_capture = {
        .substreams = 1,
        .channels_min = 2,
        .channels_max = 2,
@@ -4040,7 +4040,7 @@ static struct hda_pcm_stream ca0132_pcm_analog_capture = {
        },
 };
 
-static struct hda_pcm_stream ca0132_pcm_digital_playback = {
+static const struct hda_pcm_stream ca0132_pcm_digital_playback = {
        .substreams = 1,
        .channels_min = 2,
        .channels_max = 2,
@@ -4052,7 +4052,7 @@ static struct hda_pcm_stream ca0132_pcm_digital_playback = {
        },
 };
 
-static struct hda_pcm_stream ca0132_pcm_digital_capture = {
+static const struct hda_pcm_stream ca0132_pcm_digital_capture = {
        .substreams = 1,
        .channels_min = 2,
        .channels_max = 2,
@@ -4614,7 +4614,7 @@ static void ca0132_free(struct hda_codec *codec)
        kfree(codec->spec);
 }
 
-static struct hda_codec_ops ca0132_patch_ops = {
+static const struct hda_codec_ops ca0132_patch_ops = {
        .build_controls = ca0132_build_controls,
        .build_pcms = ca0132_build_pcms,
        .init = ca0132_init,
index 56fefbd..ed62748 100644 (file)
@@ -261,6 +261,7 @@ enum {
        CXT_FIXUP_HP_530,
        CXT_FIXUP_CAP_MIX_AMP_5047,
        CXT_FIXUP_MUTE_LED_EAPD,
+       CXT_FIXUP_HP_SPECTRE,
 };
 
 /* for hda_fixup_thinkpad_acpi() */
@@ -765,6 +766,14 @@ static const struct hda_fixup cxt_fixups[] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = cxt_fixup_mute_led_eapd,
        },
+       [CXT_FIXUP_HP_SPECTRE] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       /* enable NID 0x1d for the speaker on top */
+                       { 0x1d, 0x91170111 },
+                       { }
+               }
+       },
 };
 
 static const struct snd_pci_quirk cxt5045_fixups[] = {
@@ -814,6 +823,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = {
        SND_PCI_QUIRK(0x1025, 0x0543, "Acer Aspire One 522", CXT_FIXUP_STEREO_DMIC),
        SND_PCI_QUIRK(0x1025, 0x054c, "Acer Aspire 3830TG", CXT_FIXUP_ASPIRE_DMIC),
        SND_PCI_QUIRK(0x1025, 0x054f, "Acer Aspire 4830T", CXT_FIXUP_ASPIRE_DMIC),
+       SND_PCI_QUIRK(0x103c, 0x8174, "HP Spectre x360", CXT_FIXUP_HP_SPECTRE),
        SND_PCI_QUIRK(0x1043, 0x138d, "Asus", CXT_FIXUP_HEADPHONE_MIC_PIN),
        SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT_FIXUP_OLPC_XO),
        SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400", CXT_PINCFG_LENOVO_TP410),
index 575cefd..b58e8c7 100644 (file)
@@ -5264,6 +5264,8 @@ static const struct hda_fixup alc269_fixups[] = {
        [ALC269_FIXUP_THINKPAD_ACPI] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = hda_fixup_thinkpad_acpi,
+               .chained = true,
+               .chain_id = ALC269_FIXUP_SKU_IGNORE,
        },
        [ALC269_FIXUP_DMIC_THINKPAD_ACPI] = {
                .type = HDA_FIXUP_FUNC,
@@ -5806,6 +5808,13 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
        {0x14, 0x90170110}, \
        {0x15, 0x0221401f}
 
+#define ALC295_STANDARD_PINS \
+       {0x12, 0xb7a60130}, \
+       {0x14, 0x90170110}, \
+       {0x17, 0x21014020}, \
+       {0x18, 0x21a19030}, \
+       {0x21, 0x04211020}
+
 #define ALC298_STANDARD_PINS \
        {0x12, 0x90a60130}, \
        {0x21, 0x03211020}
@@ -5845,6 +5854,10 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
                {0x12, 0x90a60160},
                {0x14, 0x90170120},
                {0x21, 0x02211030}),
+       SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
+               {0x14, 0x90170110},
+               {0x1b, 0x02011020},
+               {0x21, 0x0221101f}),
        SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
                {0x14, 0x90170130},
                {0x1b, 0x01014020},
@@ -5910,6 +5923,10 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
                {0x12, 0x90a60180},
                {0x14, 0x90170120},
                {0x21, 0x02211030}),
+       SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
+               {0x12, 0xb7a60130},
+               {0x14, 0x90170110},
+               {0x21, 0x02211020}),
        SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
                ALC256_STANDARD_PINS),
        SND_HDA_PIN_QUIRK(0x10ec0280, 0x103c, "HP", ALC280_FIXUP_HP_GPIO4,
@@ -6021,6 +6038,8 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
        SND_HDA_PIN_QUIRK(0x10ec0293, 0x1028, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE,
                ALC292_STANDARD_PINS,
                {0x13, 0x90a60140}),
+       SND_HDA_PIN_QUIRK(0x10ec0295, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE,
+               ALC295_STANDARD_PINS),
        SND_HDA_PIN_QUIRK(0x10ec0298, 0x1028, "Dell", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE,
                ALC298_STANDARD_PINS,
                {0x17, 0x90170110}),
index 8ae3bb7..b4aa4c1 100644 (file)
@@ -847,7 +847,7 @@ static int snd_ice1712_capture_close(struct snd_pcm_substream *substream)
        return 0;
 }
 
-static struct snd_pcm_ops snd_ice1712_playback_ops = {
+static const struct snd_pcm_ops snd_ice1712_playback_ops = {
        .open =         snd_ice1712_playback_open,
        .close =        snd_ice1712_playback_close,
        .ioctl =        snd_pcm_lib_ioctl,
@@ -858,7 +858,7 @@ static struct snd_pcm_ops snd_ice1712_playback_ops = {
        .pointer =      snd_ice1712_playback_pointer,
 };
 
-static struct snd_pcm_ops snd_ice1712_playback_ds_ops = {
+static const struct snd_pcm_ops snd_ice1712_playback_ds_ops = {
        .open =         snd_ice1712_playback_ds_open,
        .close =        snd_ice1712_playback_ds_close,
        .ioctl =        snd_pcm_lib_ioctl,
@@ -869,7 +869,7 @@ static struct snd_pcm_ops snd_ice1712_playback_ds_ops = {
        .pointer =      snd_ice1712_playback_ds_pointer,
 };
 
-static struct snd_pcm_ops snd_ice1712_capture_ops = {
+static const struct snd_pcm_ops snd_ice1712_capture_ops = {
        .open =         snd_ice1712_capture_open,
        .close =        snd_ice1712_capture_close,
        .ioctl =        snd_pcm_lib_ioctl,
@@ -1228,7 +1228,7 @@ static int snd_ice1712_capture_pro_close(struct snd_pcm_substream *substream)
        return 0;
 }
 
-static struct snd_pcm_ops snd_ice1712_playback_pro_ops = {
+static const struct snd_pcm_ops snd_ice1712_playback_pro_ops = {
        .open =         snd_ice1712_playback_pro_open,
        .close =        snd_ice1712_playback_pro_close,
        .ioctl =        snd_pcm_lib_ioctl,
@@ -1239,7 +1239,7 @@ static struct snd_pcm_ops snd_ice1712_playback_pro_ops = {
        .pointer =      snd_ice1712_playback_pro_pointer,
 };
 
-static struct snd_pcm_ops snd_ice1712_capture_pro_ops = {
+static const struct snd_pcm_ops snd_ice1712_capture_pro_ops = {
        .open =         snd_ice1712_capture_pro_open,
        .close =        snd_ice1712_capture_pro_close,
        .ioctl =        snd_pcm_lib_ioctl,
index 0b22c00..e5c52ed 100644 (file)
@@ -620,9 +620,7 @@ static const unsigned int stdclock_rate_list[16] = {
 
 static unsigned int stdclock_get_rate(struct snd_ice1712 *ice)
 {
-       unsigned int rate;
-       rate = stdclock_rate_list[inb(ICEMT1724(ice, RATE)) & 15];
-       return rate;
+       return stdclock_rate_list[inb(ICEMT1724(ice, RATE)) & 15];
 }
 
 static void stdclock_set_rate(struct snd_ice1712 *ice, unsigned int rate)
@@ -1113,7 +1111,7 @@ static int snd_vt1724_capture_pro_close(struct snd_pcm_substream *substream)
        return 0;
 }
 
-static struct snd_pcm_ops snd_vt1724_playback_pro_ops = {
+static const struct snd_pcm_ops snd_vt1724_playback_pro_ops = {
        .open =         snd_vt1724_playback_pro_open,
        .close =        snd_vt1724_playback_pro_close,
        .ioctl =        snd_pcm_lib_ioctl,
@@ -1124,7 +1122,7 @@ static struct snd_pcm_ops snd_vt1724_playback_pro_ops = {
        .pointer =      snd_vt1724_playback_pro_pointer,
 };
 
-static struct snd_pcm_ops snd_vt1724_capture_pro_ops = {
+static const struct snd_pcm_ops snd_vt1724_capture_pro_ops = {
        .open =         snd_vt1724_capture_pro_open,
        .close =        snd_vt1724_capture_pro_close,
        .ioctl =        snd_pcm_lib_ioctl,
@@ -1292,7 +1290,7 @@ static int snd_vt1724_capture_spdif_close(struct snd_pcm_substream *substream)
        return 0;
 }
 
-static struct snd_pcm_ops snd_vt1724_playback_spdif_ops = {
+static const struct snd_pcm_ops snd_vt1724_playback_spdif_ops = {
        .open =         snd_vt1724_playback_spdif_open,
        .close =        snd_vt1724_playback_spdif_close,
        .ioctl =        snd_pcm_lib_ioctl,
@@ -1303,7 +1301,7 @@ static struct snd_pcm_ops snd_vt1724_playback_spdif_ops = {
        .pointer =      snd_vt1724_pcm_pointer,
 };
 
-static struct snd_pcm_ops snd_vt1724_capture_spdif_ops = {
+static const struct snd_pcm_ops snd_vt1724_capture_spdif_ops = {
        .open =         snd_vt1724_capture_spdif_open,
        .close =        snd_vt1724_capture_spdif_close,
        .ioctl =        snd_pcm_lib_ioctl,
@@ -1437,7 +1435,7 @@ static int snd_vt1724_playback_indep_close(struct snd_pcm_substream *substream)
        return 0;
 }
 
-static struct snd_pcm_ops snd_vt1724_playback_indep_ops = {
+static const struct snd_pcm_ops snd_vt1724_playback_indep_ops = {
        .open =         snd_vt1724_playback_indep_open,
        .close =        snd_vt1724_playback_indep_close,
        .ioctl =        snd_pcm_lib_ioctl,
index 9e1ad11..565f7f5 100644 (file)
@@ -1681,7 +1681,7 @@ static int snd_korg1212_capture_copy(struct snd_pcm_substream *substream,
        return snd_korg1212_copy_to(korg1212, dst, pos, count, 0, korg1212->channels * 2);
 }
 
-static struct snd_pcm_ops snd_korg1212_playback_ops = {
+static const struct snd_pcm_ops snd_korg1212_playback_ops = {
         .open =                snd_korg1212_playback_open,
         .close =       snd_korg1212_playback_close,
         .ioctl =       snd_korg1212_ioctl,
@@ -1693,7 +1693,7 @@ static struct snd_pcm_ops snd_korg1212_playback_ops = {
         .silence =     snd_korg1212_playback_silence,
 };
 
-static struct snd_pcm_ops snd_korg1212_capture_ops = {
+static const struct snd_pcm_ops snd_korg1212_capture_ops = {
        .open =         snd_korg1212_capture_open,
        .close =        snd_korg1212_capture_close,
        .ioctl =        snd_korg1212_ioctl,
index 3bd6985..1268ba3 100644 (file)
@@ -586,7 +586,7 @@ void lola_pcm_update(struct lola *chip, struct lola_pcm *pcm, unsigned int bits)
        }
 }
 
-static struct snd_pcm_ops lola_pcm_ops = {
+static const struct snd_pcm_ops lola_pcm_ops = {
        .open = lola_pcm_open,
        .close = lola_pcm_close,
        .ioctl = snd_pcm_lib_ioctl,
index 8b8e2e5..c0f0c34 100644 (file)
@@ -804,7 +804,7 @@ mac_ready:
        return err;
 }
 
-static struct snd_pcm_ops lx_ops_playback = {
+static const struct snd_pcm_ops lx_ops_playback = {
        .open      = lx_pcm_open,
        .close     = lx_pcm_close,
        .ioctl     = snd_pcm_lib_ioctl,
@@ -815,7 +815,7 @@ static struct snd_pcm_ops lx_ops_playback = {
        .pointer   = lx_pcm_stream_pointer,
 };
 
-static struct snd_pcm_ops lx_ops_capture = {
+static const struct snd_pcm_ops lx_ops_capture = {
        .open      = lx_pcm_open,
        .close     = lx_pcm_close,
        .ioctl     = snd_pcm_lib_ioctl,
index 17ae926..cafea6d 100644 (file)
@@ -1834,7 +1834,7 @@ snd_m3_capture_close(struct snd_pcm_substream *subs)
  * create pcm instance
  */
 
-static struct snd_pcm_ops snd_m3_playback_ops = {
+static const struct snd_pcm_ops snd_m3_playback_ops = {
        .open =         snd_m3_playback_open,
        .close =        snd_m3_playback_close,
        .ioctl =        snd_pcm_lib_ioctl,
@@ -1845,7 +1845,7 @@ static struct snd_pcm_ops snd_m3_playback_ops = {
        .pointer =      snd_m3_pcm_pointer,
 };
 
-static struct snd_pcm_ops snd_m3_capture_ops = {
+static const struct snd_pcm_ops snd_m3_capture_ops = {
        .open =         snd_m3_capture_open,
        .close =        snd_m3_capture_close,
        .ioctl =        snd_pcm_lib_ioctl,
index 25c0ddd..80d4399 100644 (file)
@@ -922,7 +922,7 @@ static snd_pcm_uframes_t snd_mixart_stream_pointer(struct snd_pcm_substream *sub
 
 
 
-static struct snd_pcm_ops snd_mixart_playback_ops = {
+static const struct snd_pcm_ops snd_mixart_playback_ops = {
        .open      = snd_mixart_playback_open,
        .close     = snd_mixart_close,
        .ioctl     = snd_pcm_lib_ioctl,
@@ -933,7 +933,7 @@ static struct snd_pcm_ops snd_mixart_playback_ops = {
        .pointer   = snd_mixart_stream_pointer,
 };
 
-static struct snd_pcm_ops snd_mixart_capture_ops = {
+static const struct snd_pcm_ops snd_mixart_capture_ops = {
        .open      = snd_mixart_capture_open,
        .close     = snd_mixart_close,
        .ioctl     = snd_pcm_lib_ioctl,
index 4735e27..103fe31 100644 (file)
@@ -902,7 +902,7 @@ snd_nm256_capture_close(struct snd_pcm_substream *substream)
 /*
  * create a pcm instance
  */
-static struct snd_pcm_ops snd_nm256_playback_ops = {
+static const struct snd_pcm_ops snd_nm256_playback_ops = {
        .open =         snd_nm256_playback_open,
        .close =        snd_nm256_playback_close,
        .ioctl =        snd_pcm_lib_ioctl,
@@ -917,7 +917,7 @@ static struct snd_pcm_ops snd_nm256_playback_ops = {
        .mmap =         snd_pcm_lib_mmap_iomem,
 };
 
-static struct snd_pcm_ops snd_nm256_capture_ops = {
+static const struct snd_pcm_ops snd_nm256_capture_ops = {
        .open =         snd_nm256_capture_open,
        .close =        snd_nm256_capture_close,
        .ioctl =        snd_pcm_lib_ioctl,
index aa2ebd1..042a243 100644 (file)
@@ -631,7 +631,7 @@ static snd_pcm_uframes_t oxygen_pointer(struct snd_pcm_substream *substream)
        return bytes_to_frames(runtime, curr_addr - (u32)runtime->dma_addr);
 }
 
-static struct snd_pcm_ops oxygen_rec_a_ops = {
+static const struct snd_pcm_ops oxygen_rec_a_ops = {
        .open      = oxygen_rec_a_open,
        .close     = oxygen_close,
        .ioctl     = snd_pcm_lib_ioctl,
@@ -642,7 +642,7 @@ static struct snd_pcm_ops oxygen_rec_a_ops = {
        .pointer   = oxygen_pointer,
 };
 
-static struct snd_pcm_ops oxygen_rec_b_ops = {
+static const struct snd_pcm_ops oxygen_rec_b_ops = {
        .open      = oxygen_rec_b_open,
        .close     = oxygen_close,
        .ioctl     = snd_pcm_lib_ioctl,
@@ -653,7 +653,7 @@ static struct snd_pcm_ops oxygen_rec_b_ops = {
        .pointer   = oxygen_pointer,
 };
 
-static struct snd_pcm_ops oxygen_rec_c_ops = {
+static const struct snd_pcm_ops oxygen_rec_c_ops = {
        .open      = oxygen_rec_c_open,
        .close     = oxygen_close,
        .ioctl     = snd_pcm_lib_ioctl,
@@ -664,7 +664,7 @@ static struct snd_pcm_ops oxygen_rec_c_ops = {
        .pointer   = oxygen_pointer,
 };
 
-static struct snd_pcm_ops oxygen_spdif_ops = {
+static const struct snd_pcm_ops oxygen_spdif_ops = {
        .open      = oxygen_spdif_open,
        .close     = oxygen_close,
        .ioctl     = snd_pcm_lib_ioctl,
@@ -675,7 +675,7 @@ static struct snd_pcm_ops oxygen_spdif_ops = {
        .pointer   = oxygen_pointer,
 };
 
-static struct snd_pcm_ops oxygen_multich_ops = {
+static const struct snd_pcm_ops oxygen_multich_ops = {
        .open      = oxygen_multich_open,
        .close     = oxygen_close,
        .ioctl     = snd_pcm_lib_ioctl,
@@ -686,7 +686,7 @@ static struct snd_pcm_ops oxygen_multich_ops = {
        .pointer   = oxygen_pointer,
 };
 
-static struct snd_pcm_ops oxygen_ac97_ops = {
+static const struct snd_pcm_ops oxygen_ac97_ops = {
        .open      = oxygen_ac97_open,
        .close     = oxygen_close,
        .ioctl     = snd_pcm_lib_ioctl,
index 9293235..bb7eee9 100644 (file)
@@ -1146,7 +1146,7 @@ static snd_pcm_uframes_t pcxhr_stream_pointer(struct snd_pcm_substream *subs)
 }
 
 
-static struct snd_pcm_ops pcxhr_ops = {
+static const struct snd_pcm_ops pcxhr_ops = {
        .open      = pcxhr_open,
        .close     = pcxhr_close,
        .ioctl     = snd_pcm_lib_ioctl,
index 067a912..ada5f01 100644 (file)
@@ -644,7 +644,7 @@ static struct lbuspath lbus_play_paths[] = {
         .mono = lbus_play_mono3,
         },
 };
-static struct lbuspath lbus_rec_path = {
+static const struct lbuspath lbus_rec_path = {
        .noconv = lbus_rec_noconv1,
        .stereo = lbus_rec_stereo1,
        .mono = lbus_rec_mono1,
@@ -1669,7 +1669,7 @@ static int snd_riptide_capture_close(struct snd_pcm_substream *substream)
        return 0;
 }
 
-static struct snd_pcm_ops snd_riptide_playback_ops = {
+static const struct snd_pcm_ops snd_riptide_playback_ops = {
        .open = snd_riptide_playback_open,
        .close = snd_riptide_playback_close,
        .ioctl = snd_pcm_lib_ioctl,
@@ -1680,7 +1680,7 @@ static struct snd_pcm_ops snd_riptide_playback_ops = {
        .trigger = snd_riptide_trigger,
        .pointer = snd_riptide_pointer,
 };
-static struct snd_pcm_ops snd_riptide_capture_ops = {
+static const struct snd_pcm_ops snd_riptide_capture_ops = {
        .open = snd_riptide_capture_open,
        .close = snd_riptide_capture_close,
        .ioctl = snd_pcm_lib_ioctl,
index cd94ac5..96d15db 100644 (file)
@@ -1196,7 +1196,7 @@ snd_rme32_capture_fd_pointer(struct snd_pcm_substream *substream)
 }
 
 /* for halfduplex mode */
-static struct snd_pcm_ops snd_rme32_playback_spdif_ops = {
+static const struct snd_pcm_ops snd_rme32_playback_spdif_ops = {
        .open =         snd_rme32_playback_spdif_open,
        .close =        snd_rme32_playback_close,
        .ioctl =        snd_pcm_lib_ioctl,
@@ -1210,7 +1210,7 @@ static struct snd_pcm_ops snd_rme32_playback_spdif_ops = {
        .mmap =         snd_pcm_lib_mmap_iomem,
 };
 
-static struct snd_pcm_ops snd_rme32_capture_spdif_ops = {
+static const struct snd_pcm_ops snd_rme32_capture_spdif_ops = {
        .open =         snd_rme32_capture_spdif_open,
        .close =        snd_rme32_capture_close,
        .ioctl =        snd_pcm_lib_ioctl,
@@ -1223,7 +1223,7 @@ static struct snd_pcm_ops snd_rme32_capture_spdif_ops = {
        .mmap =         snd_pcm_lib_mmap_iomem,
 };
 
-static struct snd_pcm_ops snd_rme32_playback_adat_ops = {
+static const struct snd_pcm_ops snd_rme32_playback_adat_ops = {
        .open =         snd_rme32_playback_adat_open,
        .close =        snd_rme32_playback_close,
        .ioctl =        snd_pcm_lib_ioctl,
@@ -1236,7 +1236,7 @@ static struct snd_pcm_ops snd_rme32_playback_adat_ops = {
        .mmap =         snd_pcm_lib_mmap_iomem,
 };
 
-static struct snd_pcm_ops snd_rme32_capture_adat_ops = {
+static const struct snd_pcm_ops snd_rme32_capture_adat_ops = {
        .open =         snd_rme32_capture_adat_open,
        .close =        snd_rme32_capture_close,
        .ioctl =        snd_pcm_lib_ioctl,
@@ -1249,7 +1249,7 @@ static struct snd_pcm_ops snd_rme32_capture_adat_ops = {
 };
 
 /* for fullduplex mode */
-static struct snd_pcm_ops snd_rme32_playback_spdif_fd_ops = {
+static const struct snd_pcm_ops snd_rme32_playback_spdif_fd_ops = {
        .open =         snd_rme32_playback_spdif_open,
        .close =        snd_rme32_playback_close,
        .ioctl =        snd_pcm_lib_ioctl,
@@ -1261,7 +1261,7 @@ static struct snd_pcm_ops snd_rme32_playback_spdif_fd_ops = {
        .ack =          snd_rme32_playback_fd_ack,
 };
 
-static struct snd_pcm_ops snd_rme32_capture_spdif_fd_ops = {
+static const struct snd_pcm_ops snd_rme32_capture_spdif_fd_ops = {
        .open =         snd_rme32_capture_spdif_open,
        .close =        snd_rme32_capture_close,
        .ioctl =        snd_pcm_lib_ioctl,
@@ -1273,7 +1273,7 @@ static struct snd_pcm_ops snd_rme32_capture_spdif_fd_ops = {
        .ack =          snd_rme32_capture_fd_ack,
 };
 
-static struct snd_pcm_ops snd_rme32_playback_adat_fd_ops = {
+static const struct snd_pcm_ops snd_rme32_playback_adat_fd_ops = {
        .open =         snd_rme32_playback_adat_open,
        .close =        snd_rme32_playback_close,
        .ioctl =        snd_pcm_lib_ioctl,
@@ -1284,7 +1284,7 @@ static struct snd_pcm_ops snd_rme32_playback_adat_fd_ops = {
        .ack =          snd_rme32_playback_fd_ack,
 };
 
-static struct snd_pcm_ops snd_rme32_capture_adat_fd_ops = {
+static const struct snd_pcm_ops snd_rme32_capture_adat_fd_ops = {
        .open =         snd_rme32_capture_adat_open,
        .close =        snd_rme32_capture_close,
        .ioctl =        snd_pcm_lib_ioctl,
index 41c31db..05b9da3 100644 (file)
@@ -1505,7 +1505,7 @@ snd_rme96_capture_pointer(struct snd_pcm_substream *substream)
        return snd_rme96_capture_ptr(rme96);
 }
 
-static struct snd_pcm_ops snd_rme96_playback_spdif_ops = {
+static const struct snd_pcm_ops snd_rme96_playback_spdif_ops = {
        .open =         snd_rme96_playback_spdif_open,
        .close =        snd_rme96_playback_close,
        .ioctl =        snd_pcm_lib_ioctl,
@@ -1518,7 +1518,7 @@ static struct snd_pcm_ops snd_rme96_playback_spdif_ops = {
        .mmap =         snd_pcm_lib_mmap_iomem,
 };
 
-static struct snd_pcm_ops snd_rme96_capture_spdif_ops = {
+static const struct snd_pcm_ops snd_rme96_capture_spdif_ops = {
        .open =         snd_rme96_capture_spdif_open,
        .close =        snd_rme96_capture_close,
        .ioctl =        snd_pcm_lib_ioctl,
@@ -1530,7 +1530,7 @@ static struct snd_pcm_ops snd_rme96_capture_spdif_ops = {
        .mmap =         snd_pcm_lib_mmap_iomem,
 };
 
-static struct snd_pcm_ops snd_rme96_playback_adat_ops = {
+static const struct snd_pcm_ops snd_rme96_playback_adat_ops = {
        .open =         snd_rme96_playback_adat_open,
        .close =        snd_rme96_playback_close,
        .ioctl =        snd_pcm_lib_ioctl,
@@ -1543,7 +1543,7 @@ static struct snd_pcm_ops snd_rme96_playback_adat_ops = {
        .mmap =         snd_pcm_lib_mmap_iomem,
 };
 
-static struct snd_pcm_ops snd_rme96_capture_adat_ops = {
+static const struct snd_pcm_ops snd_rme96_capture_adat_ops = {
        .open =         snd_rme96_capture_adat_open,
        .close =        snd_rme96_capture_close,
        .ioctl =        snd_pcm_lib_ioctl,
index 7c8941b..b94fc63 100644 (file)
@@ -4861,7 +4861,7 @@ static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigne
        return 0;
 }
 
-static struct snd_pcm_ops snd_hdsp_playback_ops = {
+static const struct snd_pcm_ops snd_hdsp_playback_ops = {
        .open =         snd_hdsp_playback_open,
        .close =        snd_hdsp_playback_release,
        .ioctl =        snd_hdsp_ioctl,
@@ -4873,7 +4873,7 @@ static struct snd_pcm_ops snd_hdsp_playback_ops = {
        .silence =      snd_hdsp_hw_silence,
 };
 
-static struct snd_pcm_ops snd_hdsp_capture_ops = {
+static const struct snd_pcm_ops snd_hdsp_capture_ops = {
        .open =         snd_hdsp_capture_open,
        .close =        snd_hdsp_capture_release,
        .ioctl =        snd_hdsp_ioctl,
index a4a999a..14bbf55 100644 (file)
@@ -1666,7 +1666,7 @@ static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally)
                            HDSPM_AUTOSYNC_FROM_NONE) {
 
                                dev_warn(hdspm->card->dev,
-                                        "Detected no Externel Sync\n");
+                                        "Detected no External Sync\n");
                                not_set = 1;
 
                        } else if (rate != external_freq) {
@@ -6361,7 +6361,7 @@ static int snd_hdspm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
        return 0;
 }
 
-static struct snd_pcm_ops snd_hdspm_ops = {
+static const struct snd_pcm_ops snd_hdspm_ops = {
        .open = snd_hdspm_open,
        .close = snd_hdspm_release,
        .ioctl = snd_hdspm_ioctl,
index fdbc0aa..55172c6 100644 (file)
@@ -2368,7 +2368,7 @@ static int snd_rme9652_capture_release(struct snd_pcm_substream *substream)
        return 0;
 }
 
-static struct snd_pcm_ops snd_rme9652_playback_ops = {
+static const struct snd_pcm_ops snd_rme9652_playback_ops = {
        .open =         snd_rme9652_playback_open,
        .close =        snd_rme9652_playback_release,
        .ioctl =        snd_rme9652_ioctl,
@@ -2380,7 +2380,7 @@ static struct snd_pcm_ops snd_rme9652_playback_ops = {
        .silence =      snd_rme9652_hw_silence,
 };
 
-static struct snd_pcm_ops snd_rme9652_capture_ops = {
+static const struct snd_pcm_ops snd_rme9652_capture_ops = {
        .open =         snd_rme9652_capture_open,
        .close =        snd_rme9652_capture_release,
        .ioctl =        snd_rme9652_ioctl,
index 1b6fad7..e1a1387 100644 (file)
@@ -857,7 +857,7 @@ static int snd_sonicvibes_capture_close(struct snd_pcm_substream *substream)
        return 0;
 }
 
-static struct snd_pcm_ops snd_sonicvibes_playback_ops = {
+static const struct snd_pcm_ops snd_sonicvibes_playback_ops = {
        .open =         snd_sonicvibes_playback_open,
        .close =        snd_sonicvibes_playback_close,
        .ioctl =        snd_pcm_lib_ioctl,
@@ -868,7 +868,7 @@ static struct snd_pcm_ops snd_sonicvibes_playback_ops = {
        .pointer =      snd_sonicvibes_playback_pointer,
 };
 
-static struct snd_pcm_ops snd_sonicvibes_capture_ops = {
+static const struct snd_pcm_ops snd_sonicvibes_capture_ops = {
        .open =         snd_sonicvibes_capture_open,
        .close =        snd_sonicvibes_capture_close,
        .ioctl =        snd_pcm_lib_ioctl,
index 599d2b7..27f0ed8 100644 (file)
@@ -2070,7 +2070,7 @@ static int snd_trident_foldback_close(struct snd_pcm_substream *substream)
    PCM operations
   ---------------------------------------------------------------------------*/
 
-static struct snd_pcm_ops snd_trident_playback_ops = {
+static const struct snd_pcm_ops snd_trident_playback_ops = {
        .open =         snd_trident_playback_open,
        .close =        snd_trident_playback_close,
        .ioctl =        snd_trident_ioctl,
@@ -2081,7 +2081,7 @@ static struct snd_pcm_ops snd_trident_playback_ops = {
        .pointer =      snd_trident_playback_pointer,
 };
 
-static struct snd_pcm_ops snd_trident_nx_playback_ops = {
+static const struct snd_pcm_ops snd_trident_nx_playback_ops = {
        .open =         snd_trident_playback_open,
        .close =        snd_trident_playback_close,
        .ioctl =        snd_trident_ioctl,
@@ -2115,7 +2115,7 @@ static struct snd_pcm_ops snd_trident_si7018_capture_ops = {
        .pointer =      snd_trident_playback_pointer,
 };
 
-static struct snd_pcm_ops snd_trident_foldback_ops = {
+static const struct snd_pcm_ops snd_trident_foldback_ops = {
        .open =         snd_trident_foldback_open,
        .close =        snd_trident_foldback_close,
        .ioctl =        snd_trident_ioctl,
@@ -2126,7 +2126,7 @@ static struct snd_pcm_ops snd_trident_foldback_ops = {
        .pointer =      snd_trident_playback_pointer,
 };
 
-static struct snd_pcm_ops snd_trident_nx_foldback_ops = {
+static const struct snd_pcm_ops snd_trident_nx_foldback_ops = {
        .open =         snd_trident_foldback_open,
        .close =        snd_trident_foldback_close,
        .ioctl =        snd_trident_ioctl,
@@ -2138,7 +2138,7 @@ static struct snd_pcm_ops snd_trident_nx_foldback_ops = {
        .page =         snd_pcm_sgbuf_ops_page,
 };
 
-static struct snd_pcm_ops snd_trident_spdif_ops = {
+static const struct snd_pcm_ops snd_trident_spdif_ops = {
        .open =         snd_trident_spdif_open,
        .close =        snd_trident_spdif_close,
        .ioctl =        snd_trident_ioctl,
@@ -2149,7 +2149,7 @@ static struct snd_pcm_ops snd_trident_spdif_ops = {
        .pointer =      snd_trident_spdif_pointer,
 };
 
-static struct snd_pcm_ops snd_trident_spdif_7018_ops = {
+static const struct snd_pcm_ops snd_trident_spdif_7018_ops = {
        .open =         snd_trident_spdif_open,
        .close =        snd_trident_spdif_close,
        .ioctl =        snd_trident_ioctl,
index 3dd038b..38a17b4 100644 (file)
@@ -1366,7 +1366,7 @@ static int snd_via8233_playback_close(struct snd_pcm_substream *substream)
 
 
 /* via686 playback callbacks */
-static struct snd_pcm_ops snd_via686_playback_ops = {
+static const struct snd_pcm_ops snd_via686_playback_ops = {
        .open =         snd_via686_playback_open,
        .close =        snd_via82xx_pcm_close,
        .ioctl =        snd_pcm_lib_ioctl,
@@ -1379,7 +1379,7 @@ static struct snd_pcm_ops snd_via686_playback_ops = {
 };
 
 /* via686 capture callbacks */
-static struct snd_pcm_ops snd_via686_capture_ops = {
+static const struct snd_pcm_ops snd_via686_capture_ops = {
        .open =         snd_via82xx_capture_open,
        .close =        snd_via82xx_pcm_close,
        .ioctl =        snd_pcm_lib_ioctl,
@@ -1392,7 +1392,7 @@ static struct snd_pcm_ops snd_via686_capture_ops = {
 };
 
 /* via823x DSX playback callbacks */
-static struct snd_pcm_ops snd_via8233_playback_ops = {
+static const struct snd_pcm_ops snd_via8233_playback_ops = {
        .open =         snd_via8233_playback_open,
        .close =        snd_via8233_playback_close,
        .ioctl =        snd_pcm_lib_ioctl,
@@ -1405,7 +1405,7 @@ static struct snd_pcm_ops snd_via8233_playback_ops = {
 };
 
 /* via823x multi-channel playback callbacks */
-static struct snd_pcm_ops snd_via8233_multi_ops = {
+static const struct snd_pcm_ops snd_via8233_multi_ops = {
        .open =         snd_via8233_multi_open,
        .close =        snd_via82xx_pcm_close,
        .ioctl =        snd_pcm_lib_ioctl,
@@ -1418,7 +1418,7 @@ static struct snd_pcm_ops snd_via8233_multi_ops = {
 };
 
 /* via823x capture callbacks */
-static struct snd_pcm_ops snd_via8233_capture_ops = {
+static const struct snd_pcm_ops snd_via8233_capture_ops = {
        .open =         snd_via82xx_capture_open,
        .close =        snd_via82xx_pcm_close,
        .ioctl =        snd_pcm_lib_ioctl,
index 99b9137..2f6d40f 100644 (file)
@@ -804,7 +804,7 @@ static int snd_via82xx_pcm_close(struct snd_pcm_substream *substream)
 
 
 /* via686 playback callbacks */
-static struct snd_pcm_ops snd_via686_playback_ops = {
+static const struct snd_pcm_ops snd_via686_playback_ops = {
        .open =         snd_via82xx_playback_open,
        .close =        snd_via82xx_pcm_close,
        .ioctl =        snd_pcm_lib_ioctl,
@@ -817,7 +817,7 @@ static struct snd_pcm_ops snd_via686_playback_ops = {
 };
 
 /* via686 capture callbacks */
-static struct snd_pcm_ops snd_via686_capture_ops = {
+static const struct snd_pcm_ops snd_via686_capture_ops = {
        .open =         snd_via82xx_capture_open,
        .close =        snd_via82xx_pcm_close,
        .ioctl =        snd_pcm_lib_ioctl,
index 4c26076..ffee284 100644 (file)
@@ -1123,7 +1123,7 @@ static int snd_ymfpci_capture_close(struct snd_pcm_substream *substream)
        return 0;
 }
 
-static struct snd_pcm_ops snd_ymfpci_playback_ops = {
+static const struct snd_pcm_ops snd_ymfpci_playback_ops = {
        .open =                 snd_ymfpci_playback_open,
        .close =                snd_ymfpci_playback_close,
        .ioctl =                snd_pcm_lib_ioctl,
@@ -1134,7 +1134,7 @@ static struct snd_pcm_ops snd_ymfpci_playback_ops = {
        .pointer =              snd_ymfpci_playback_pointer,
 };
 
-static struct snd_pcm_ops snd_ymfpci_capture_rec_ops = {
+static const struct snd_pcm_ops snd_ymfpci_capture_rec_ops = {
        .open =                 snd_ymfpci_capture_rec_open,
        .close =                snd_ymfpci_capture_close,
        .ioctl =                snd_pcm_lib_ioctl,
@@ -1169,7 +1169,7 @@ int snd_ymfpci_pcm(struct snd_ymfpci *chip, int device)
                                     snd_pcm_std_chmaps, 2, 0, NULL);
 }
 
-static struct snd_pcm_ops snd_ymfpci_capture_ac97_ops = {
+static const struct snd_pcm_ops snd_ymfpci_capture_ac97_ops = {
        .open =                 snd_ymfpci_capture_ac97_open,
        .close =                snd_ymfpci_capture_close,
        .ioctl =                snd_pcm_lib_ioctl,
@@ -1203,7 +1203,7 @@ int snd_ymfpci_pcm2(struct snd_ymfpci *chip, int device)
        return 0;
 }
 
-static struct snd_pcm_ops snd_ymfpci_playback_spdif_ops = {
+static const struct snd_pcm_ops snd_ymfpci_playback_spdif_ops = {
        .open =                 snd_ymfpci_playback_spdif_open,
        .close =                snd_ymfpci_playback_spdif_close,
        .ioctl =                snd_pcm_lib_ioctl,
@@ -1236,7 +1236,7 @@ int snd_ymfpci_pcm_spdif(struct snd_ymfpci *chip, int device)
        return 0;
 }
 
-static struct snd_pcm_ops snd_ymfpci_playback_4ch_ops = {
+static const struct snd_pcm_ops snd_ymfpci_playback_4ch_ops = {
        .open =                 snd_ymfpci_playback_4ch_open,
        .close =                snd_ymfpci_playback_4ch_close,
        .ioctl =                snd_pcm_lib_ioctl,
index 3682425..b84d7d3 100644 (file)
@@ -564,9 +564,7 @@ static int snd_ps3_pcm_hw_params(struct snd_pcm_substream *substream,
 
 static int snd_ps3_pcm_hw_free(struct snd_pcm_substream *substream)
 {
-       int ret;
-       ret = snd_pcm_lib_free_pages(substream);
-       return ret;
+       return snd_pcm_lib_free_pages(substream);
 };
 
 static int snd_ps3_delay_to_bytes(struct snd_pcm_substream *substream,
index 5bbaa66..c8455b4 100644 (file)
@@ -184,15 +184,9 @@ struct sst_byt {
 
 static inline u64 sst_byt_header(int msg_id, int data, bool large, int str_id)
 {
-       u64 header;
-
-       header = IPC_HEADER_MSG_ID(msg_id) |
-                IPC_HEADER_STR_ID(str_id) |
-                IPC_HEADER_LARGE(large) |
-                IPC_HEADER_DATA(data) |
-                SST_BYT_IPCX_BUSY;
-
-       return header;
+       return IPC_HEADER_MSG_ID(msg_id) | IPC_HEADER_STR_ID(str_id) |
+              IPC_HEADER_LARGE(large) | IPC_HEADER_DATA(data) |
+              SST_BYT_IPCX_BUSY;
 }
 
 static inline u16 sst_byt_header_msg_id(u64 header)
index 327f864..8f66ba7 100644 (file)
@@ -739,7 +739,6 @@ static struct urb **alloc_urbs(struct snd_usb_caiaqdev *cdev, int dir, int *ret)
        for (i = 0; i < N_URBS; i++) {
                urbs[i] = usb_alloc_urb(FRAMES_PER_URB, GFP_KERNEL);
                if (!urbs[i]) {
-                       dev_err(dev, "unable to usb_alloc_urb(), OOM!?\n");
                        *ret = -ENOMEM;
                        return urbs;
                }
index 71778ca..111b0f0 100644 (file)
@@ -92,7 +92,7 @@ struct snd_usb_endpoint {
        unsigned int curframesize;      /* current packet size in frames (for capture) */
        unsigned int syncmaxsize;       /* sync endpoint packet size */
        unsigned int fill_max:1;        /* fill max packet size always */
-       unsigned int udh01_fb_quirk:1;  /* corrupted feedback data */
+       unsigned int tenor_fb_quirk:1;  /* corrupted feedback data */
        unsigned int datainterval;      /* log_2 of data packet interval */
        unsigned int syncinterval;      /* P for adaptive mode, 0 otherwise */
        unsigned char silence_value;
index c07a7ed..c470251 100644 (file)
@@ -502,10 +502,6 @@ struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip,
                        ep->syncinterval = 3;
 
                ep->syncmaxsize = le16_to_cpu(get_endpoint(alts, 1)->wMaxPacketSize);
-
-               if (chip->usb_id == USB_ID(0x0644, 0x8038) /* TEAC UD-H01 */ &&
-                   ep->syncmaxsize == 4)
-                       ep->udh01_fb_quirk = 1;
        }
 
        list_add_tail(&ep->list, &chip->ep_list);
@@ -1171,15 +1167,16 @@ void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep,
        if (f == 0)
                return;
 
-       if (unlikely(sender->udh01_fb_quirk)) {
+       if (unlikely(sender->tenor_fb_quirk)) {
                /*
-                * The TEAC UD-H01 firmware sometimes changes the feedback value
+                * Devices based on Tenor 8802 chipsets (TEAC UD-H01
+                * and others) sometimes change the feedback value
                 * by +/- 0x1.0000.
                 */
                if (f < ep->freqn - 0x8000)
-                       f += 0x10000;
+                       f += 0xf000;
                else if (f > ep->freqn + 0x8000)
-                       f -= 0x10000;
+                       f -= 0xf000;
        } else if (unlikely(ep->freqshift == INT_MIN)) {
                /*
                 * The first time we see a feedback value, determine its format
index 789d19e..2c44386 100644 (file)
@@ -176,10 +176,8 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof
                int r, idx;
 
                fp->rate_table = kmalloc(sizeof(int) * nr_rates, GFP_KERNEL);
-               if (fp->rate_table == NULL) {
-                       usb_audio_err(chip, "cannot malloc\n");
+               if (fp->rate_table == NULL)
                        return -ENOMEM;
-               }
 
                fp->nr_rates = 0;
                fp->rate_min = fp->rate_max = 0;
index f4585d3..39b4003 100644 (file)
@@ -2,6 +2,7 @@ config SND_USB_LINE6
        tristate
        select SND_RAWMIDI
        select SND_PCM
+       select SND_HWDEP
 
 config SND_USB_POD
        tristate "Line 6 POD USB support"
@@ -21,10 +22,10 @@ config SND_USB_POD
              re-amping)
 
 config SND_USB_PODHD
-       tristate "Line 6 POD HD300/400/500 USB support"
+       tristate "Line 6 POD X3/HD300/400/500 USB support"
        select SND_USB_LINE6
        help
-         This is a driver for POD HD300, 400 and 500 devices.
+         This is a driver for POD X3, HD300, 400 and 500 devices.
 
 config SND_USB_TONEPORT
        tristate "TonePort GX, UX1 and UX2 USB support"
index f518fbb..7c81256 100644 (file)
@@ -29,10 +29,10 @@ static int submit_audio_in_urb(struct snd_line6_pcm *line6pcm)
        int ret;
        struct urb *urb_in;
 
-       index =
-           find_first_zero_bit(&line6pcm->in.active_urbs, LINE6_ISO_BUFFERS);
+       index = find_first_zero_bit(&line6pcm->in.active_urbs,
+                                   line6pcm->line6->iso_buffers);
 
-       if (index < 0 || index >= LINE6_ISO_BUFFERS) {
+       if (index < 0 || index >= line6pcm->line6->iso_buffers) {
                dev_err(line6pcm->line6->ifcdev, "no free URB found\n");
                return -EINVAL;
        }
@@ -44,13 +44,13 @@ static int submit_audio_in_urb(struct snd_line6_pcm *line6pcm)
                struct usb_iso_packet_descriptor *fin =
                    &urb_in->iso_frame_desc[i];
                fin->offset = urb_size;
-               fin->length = line6pcm->max_packet_size;
-               urb_size += line6pcm->max_packet_size;
+               fin->length = line6pcm->max_packet_size_in;
+               urb_size += line6pcm->max_packet_size_in;
        }
 
        urb_in->transfer_buffer =
            line6pcm->in.buffer +
-           index * LINE6_ISO_PACKETS * line6pcm->max_packet_size;
+           index * LINE6_ISO_PACKETS * line6pcm->max_packet_size_in;
        urb_in->transfer_buffer_length = urb_size;
        urb_in->context = line6pcm;
 
@@ -73,7 +73,7 @@ int line6_submit_audio_in_all_urbs(struct snd_line6_pcm *line6pcm)
 {
        int ret = 0, i;
 
-       for (i = 0; i < LINE6_ISO_BUFFERS; ++i) {
+       for (i = 0; i < line6pcm->line6->iso_buffers; ++i) {
                ret = submit_audio_in_urb(line6pcm);
                if (ret < 0)
                        break;
@@ -90,7 +90,9 @@ void line6_capture_copy(struct snd_line6_pcm *line6pcm, char *fbuf, int fsize)
        struct snd_pcm_substream *substream =
            get_substream(line6pcm, SNDRV_PCM_STREAM_CAPTURE);
        struct snd_pcm_runtime *runtime = substream->runtime;
-       const int bytes_per_frame = line6pcm->properties->bytes_per_frame;
+       const int bytes_per_frame =
+               line6pcm->properties->bytes_per_channel *
+               line6pcm->properties->capture_hw.channels_max;
        int frames = fsize / bytes_per_frame;
 
        if (runtime == NULL)
@@ -154,7 +156,7 @@ static void audio_in_callback(struct urb *urb)
        line6pcm->in.last_frame = urb->start_frame;
 
        /* find index of URB */
-       for (index = 0; index < LINE6_ISO_BUFFERS; ++index)
+       for (index = 0; index < line6pcm->line6->iso_buffers; ++index)
                if (urb == line6pcm->in.urbs[index])
                        break;
 
@@ -173,17 +175,27 @@ static void audio_in_callback(struct urb *urb)
                fbuf = urb->transfer_buffer + fin->offset;
                fsize = fin->actual_length;
 
-               if (fsize > line6pcm->max_packet_size) {
+               if (fsize > line6pcm->max_packet_size_in) {
                        dev_err(line6pcm->line6->ifcdev,
                                "driver and/or device bug: packet too large (%d > %d)\n",
-                               fsize, line6pcm->max_packet_size);
+                               fsize, line6pcm->max_packet_size_in);
                }
 
                length += fsize;
 
-               /* the following assumes LINE6_ISO_PACKETS == 1: */
+               BUILD_BUG_ON_MSG(LINE6_ISO_PACKETS != 1,
+                       "The following code assumes LINE6_ISO_PACKETS == 1");
+               /* TODO:
+                * Also, if iso_buffers != 2, the prev frame is almost random at
+                * playback side.
+                * This needs to be redesigned. It should be "stable", but we may
+                * experience sync problems on such high-speed configs.
+                */
+
                line6pcm->prev_fbuf = fbuf;
-               line6pcm->prev_fsize = fsize;
+               line6pcm->prev_fsize = fsize /
+                       (line6pcm->properties->bytes_per_channel *
+                       line6pcm->properties->capture_hw.channels_max);
 
                if (!test_bit(LINE6_STREAM_IMPULSE, &line6pcm->in.running) &&
                    test_bit(LINE6_STREAM_PCM, &line6pcm->in.running) &&
@@ -220,6 +232,8 @@ static int snd_line6_capture_open(struct snd_pcm_substream *substream)
        if (err < 0)
                return err;
 
+       line6_pcm_acquire(line6pcm, LINE6_STREAM_CAPTURE_HELPER, false);
+
        runtime->hw = line6pcm->properties->capture_hw;
        return 0;
 }
@@ -227,6 +241,9 @@ static int snd_line6_capture_open(struct snd_pcm_substream *substream)
 /* close capture callback */
 static int snd_line6_capture_close(struct snd_pcm_substream *substream)
 {
+       struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
+
+       line6_pcm_release(line6pcm, LINE6_STREAM_CAPTURE_HELPER);
        return 0;
 }
 
@@ -247,8 +264,13 @@ int line6_create_audio_in_urbs(struct snd_line6_pcm *line6pcm)
        struct usb_line6 *line6 = line6pcm->line6;
        int i;
 
+       line6pcm->in.urbs = kzalloc(
+               sizeof(struct urb *) * line6->iso_buffers, GFP_KERNEL);
+       if (line6pcm->in.urbs == NULL)
+               return -ENOMEM;
+
        /* create audio URBs and fill in constant values: */
-       for (i = 0; i < LINE6_ISO_BUFFERS; ++i) {
+       for (i = 0; i < line6->iso_buffers; ++i) {
                struct urb *urb;
 
                /* URB for audio in: */
index 81b7da8..14e587e 100644 (file)
@@ -17,6 +17,7 @@
 
 #include <sound/core.h>
 #include <sound/initval.h>
+#include <sound/hwdep.h>
 
 #include "capture.h"
 #include "driver.h"
@@ -29,7 +30,7 @@
 /*
        This is Line 6's MIDI manufacturer ID.
 */
-const unsigned char line6_midi_id[] = {
+const unsigned char line6_midi_id[3] = {
        0x00, 0x01, 0x0c
 };
 EXPORT_SYMBOL_GPL(line6_midi_id);
@@ -66,10 +67,17 @@ static int line6_start_listen(struct usb_line6 *line6)
 {
        int err;
 
-       usb_fill_int_urb(line6->urb_listen, line6->usbdev,
-               usb_rcvintpipe(line6->usbdev, line6->properties->ep_ctrl_r),
-               line6->buffer_listen, LINE6_BUFSIZE_LISTEN,
-               line6_data_received, line6, line6->interval);
+       if (line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI) {
+               usb_fill_int_urb(line6->urb_listen, line6->usbdev,
+                       usb_rcvintpipe(line6->usbdev, line6->properties->ep_ctrl_r),
+                       line6->buffer_listen, LINE6_BUFSIZE_LISTEN,
+                       line6_data_received, line6, line6->interval);
+       } else {
+               usb_fill_bulk_urb(line6->urb_listen, line6->usbdev,
+                       usb_rcvbulkpipe(line6->usbdev, line6->properties->ep_ctrl_r),
+                       line6->buffer_listen, LINE6_BUFSIZE_LISTEN,
+                       line6_data_received, line6);
+       }
        line6->urb_listen->actual_length = 0;
        err = usb_submit_urb(line6->urb_listen, GFP_ATOMIC);
        return err;
@@ -90,6 +98,7 @@ static int line6_send_raw_message(struct usb_line6 *line6, const char *buffer,
                                  int size)
 {
        int i, done = 0;
+       const struct line6_properties *properties = line6->properties;
 
        for (i = 0; i < size; i += line6->max_packet_size) {
                int partial;
@@ -97,15 +106,21 @@ static int line6_send_raw_message(struct usb_line6 *line6, const char *buffer,
                int frag_size = min(line6->max_packet_size, size - i);
                int retval;
 
-               retval = usb_interrupt_msg(line6->usbdev,
-                                       usb_sndintpipe(line6->usbdev,
-                                               line6->properties->ep_ctrl_w),
-                                       (char *)frag_buf, frag_size,
-                                       &partial, LINE6_TIMEOUT * HZ);
+               if (properties->capabilities & LINE6_CAP_CONTROL_MIDI) {
+                       retval = usb_interrupt_msg(line6->usbdev,
+                                               usb_sndintpipe(line6->usbdev, properties->ep_ctrl_w),
+                                               (char *)frag_buf, frag_size,
+                                               &partial, LINE6_TIMEOUT * HZ);
+               } else {
+                       retval = usb_bulk_msg(line6->usbdev,
+                                               usb_sndbulkpipe(line6->usbdev, properties->ep_ctrl_w),
+                                               (char *)frag_buf, frag_size,
+                                               &partial, LINE6_TIMEOUT * HZ);
+               }
 
                if (retval) {
                        dev_err(line6->ifcdev,
-                               "usb_interrupt_msg failed (%d)\n", retval);
+                               "usb_bulk_msg failed (%d)\n", retval);
                        break;
                }
 
@@ -140,10 +155,17 @@ static int line6_send_raw_message_async_part(struct message *msg,
        int done = msg->done;
        int bytes = min(msg->size - done, line6->max_packet_size);
 
-       usb_fill_int_urb(urb, line6->usbdev,
-               usb_sndintpipe(line6->usbdev, line6->properties->ep_ctrl_w),
-               (char *)msg->buffer + done, bytes,
-               line6_async_request_sent, msg, line6->interval);
+       if (line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI) {
+               usb_fill_int_urb(urb, line6->usbdev,
+                       usb_sndintpipe(line6->usbdev, line6->properties->ep_ctrl_w),
+                       (char *)msg->buffer + done, bytes,
+                       line6_async_request_sent, msg, line6->interval);
+       } else {
+               usb_fill_bulk_urb(urb, line6->usbdev,
+                       usb_sndbulkpipe(line6->usbdev, line6->properties->ep_ctrl_w),
+                       (char *)msg->buffer + done, bytes,
+                       line6_async_request_sent, msg);
+       }
 
        msg->done += bytes;
        retval = usb_submit_urb(urb, GFP_ATOMIC);
@@ -269,28 +291,36 @@ static void line6_data_received(struct urb *urb)
        if (urb->status == -ESHUTDOWN)
                return;
 
-       done =
-           line6_midibuf_write(mb, urb->transfer_buffer, urb->actual_length);
+       if (line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI) {
+               done =
+                       line6_midibuf_write(mb, urb->transfer_buffer, urb->actual_length);
 
-       if (done < urb->actual_length) {
-               line6_midibuf_ignore(mb, done);
-               dev_dbg(line6->ifcdev, "%d %d buffer overflow - message skipped\n",
-                       done, urb->actual_length);
-       }
+               if (done < urb->actual_length) {
+                       line6_midibuf_ignore(mb, done);
+                       dev_dbg(line6->ifcdev, "%d %d buffer overflow - message skipped\n",
+                               done, urb->actual_length);
+               }
 
-       for (;;) {
-               done =
-                   line6_midibuf_read(mb, line6->buffer_message,
-                                      LINE6_MESSAGE_MAXLEN);
+               for (;;) {
+                       done =
+                               line6_midibuf_read(mb, line6->buffer_message,
+                                               LINE6_MIDI_MESSAGE_MAXLEN);
 
-               if (done == 0)
-                       break;
+                       if (done == 0)
+                               break;
 
-               line6->message_length = done;
-               line6_midi_receive(line6, line6->buffer_message, done);
+                       line6->message_length = done;
+                       line6_midi_receive(line6, line6->buffer_message, done);
 
+                       if (line6->process_message)
+                               line6->process_message(line6);
+               }
+       } else {
+               line6->buffer_message = urb->transfer_buffer;
+               line6->message_length = urb->actual_length;
                if (line6->process_message)
                        line6->process_message(line6);
+               line6->buffer_message = NULL;
        }
 
        line6_start_listen(line6);
@@ -447,12 +477,16 @@ static void line6_destruct(struct snd_card *card)
        struct usb_line6 *line6 = card->private_data;
        struct usb_device *usbdev = line6->usbdev;
 
-       /* free buffer memory first: */
+       /* Free buffer memory first. We cannot depend on the existence of private
+        * data from the (podhd) module, it may be gone already during this call
+        */
        kfree(line6->buffer_message);
+
        kfree(line6->buffer_listen);
 
        /* then free URBs: */
        usb_free_urb(line6->urb_listen);
+       line6->urb_listen = NULL;
 
        /* decrement reference counters: */
        usb_put_dev(usbdev);
@@ -462,13 +496,29 @@ static void line6_destruct(struct snd_card *card)
 static void line6_get_interval(struct usb_line6 *line6)
 {
        struct usb_device *usbdev = line6->usbdev;
+       const struct line6_properties *properties = line6->properties;
+       int pipe;
        struct usb_host_endpoint *ep;
-       unsigned pipe = usb_rcvintpipe(usbdev, line6->properties->ep_ctrl_r);
-       unsigned epnum = usb_pipeendpoint(pipe);
 
-       ep = usbdev->ep_in[epnum];
+       if (properties->capabilities & LINE6_CAP_CONTROL_MIDI) {
+               pipe =
+                       usb_rcvintpipe(line6->usbdev, line6->properties->ep_ctrl_r);
+       } else {
+               pipe =
+                       usb_rcvbulkpipe(line6->usbdev, line6->properties->ep_ctrl_r);
+       }
+       ep = usbdev->ep_in[usb_pipeendpoint(pipe)];
+
        if (ep) {
                line6->interval = ep->desc.bInterval;
+               if (usbdev->speed == USB_SPEED_LOW) {
+                       line6->intervals_per_second = USB_LOW_INTERVALS_PER_SECOND;
+                       line6->iso_buffers = USB_LOW_ISO_BUFFERS;
+               } else {
+                       line6->intervals_per_second = USB_HIGH_INTERVALS_PER_SECOND;
+                       line6->iso_buffers = USB_HIGH_ISO_BUFFERS;
+               }
+
                line6->max_packet_size = le16_to_cpu(ep->desc.wMaxPacketSize);
        } else {
                dev_err(line6->ifcdev,
@@ -478,6 +528,138 @@ static void line6_get_interval(struct usb_line6 *line6)
        }
 }
 
+
+/* Enable buffering of incoming messages, flush the buffer */
+static int line6_hwdep_open(struct snd_hwdep *hw, struct file *file)
+{
+       struct usb_line6 *line6 = hw->private_data;
+
+       /* NOTE: hwdep layer provides atomicity here */
+
+       line6->messages.active = 1;
+
+       return 0;
+}
+
+/* Stop buffering */
+static int line6_hwdep_release(struct snd_hwdep *hw, struct file *file)
+{
+       struct usb_line6 *line6 = hw->private_data;
+
+       line6->messages.active = 0;
+
+       return 0;
+}
+
+/* Read from circular buffer, return to user */
+static long
+line6_hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count,
+                                       loff_t *offset)
+{
+       struct usb_line6 *line6 = hwdep->private_data;
+       long rv = 0;
+       unsigned int out_count;
+
+       if (mutex_lock_interruptible(&line6->messages.read_lock))
+               return -ERESTARTSYS;
+
+       while (kfifo_len(&line6->messages.fifo) == 0) {
+               mutex_unlock(&line6->messages.read_lock);
+
+               rv = wait_event_interruptible(
+                       line6->messages.wait_queue,
+                       kfifo_len(&line6->messages.fifo) != 0);
+               if (rv < 0)
+                       return rv;
+
+               if (mutex_lock_interruptible(&line6->messages.read_lock))
+                       return -ERESTARTSYS;
+       }
+
+       if (kfifo_peek_len(&line6->messages.fifo) > count) {
+               /* Buffer too small; allow re-read of the current item... */
+               rv = -EINVAL;
+       } else {
+               rv = kfifo_to_user(&line6->messages.fifo, buf, count, &out_count);
+               if (rv == 0)
+                       rv = out_count;
+       }
+
+       mutex_unlock(&line6->messages.read_lock);
+       return rv;
+}
+
+/* Write directly (no buffering) to device by user*/
+static long
+line6_hwdep_write(struct snd_hwdep *hwdep, const char __user *data, long count,
+                                       loff_t *offset)
+{
+       struct usb_line6 *line6 = hwdep->private_data;
+       int rv;
+       char *data_copy;
+
+       if (count > line6->max_packet_size * LINE6_RAW_MESSAGES_MAXCOUNT) {
+               /* This is an arbitrary limit - still better than nothing... */
+               return -EINVAL;
+       }
+
+       data_copy = memdup_user(data, count);
+       if (IS_ERR(ERR_PTR))
+               return -ENOMEM;
+
+       rv = line6_send_raw_message(line6, data_copy, count);
+
+       kfree(data_copy);
+       return rv;
+}
+
+static const struct snd_hwdep_ops hwdep_ops = {
+       .open    = line6_hwdep_open,
+       .release = line6_hwdep_release,
+       .read    = line6_hwdep_read,
+       .write   = line6_hwdep_write,
+};
+
+/* Insert into circular buffer */
+static void line6_hwdep_push_message(struct usb_line6 *line6)
+{
+       if (!line6->messages.active)
+               return;
+
+       if (kfifo_avail(&line6->messages.fifo) >= line6->message_length) {
+               /* No race condition here, there's only one writer */
+               kfifo_in(&line6->messages.fifo,
+                       line6->buffer_message, line6->message_length);
+       } /* else TODO: signal overflow */
+
+       wake_up_interruptible(&line6->messages.wait_queue);
+}
+
+static int line6_hwdep_init(struct usb_line6 *line6)
+{
+       int err;
+       struct snd_hwdep *hwdep;
+
+       /* TODO: usb_driver_claim_interface(); */
+       line6->process_message = line6_hwdep_push_message;
+       line6->messages.active = 0;
+       init_waitqueue_head(&line6->messages.wait_queue);
+       mutex_init(&line6->messages.read_lock);
+       INIT_KFIFO(line6->messages.fifo);
+
+       err = snd_hwdep_new(line6->card, "config", 0, &hwdep);
+       if (err < 0)
+               goto end;
+       strcpy(hwdep->name, "config");
+       hwdep->iface = SNDRV_HWDEP_IFACE_LINE6;
+       hwdep->ops = hwdep_ops;
+       hwdep->private_data = line6;
+       hwdep->exclusive = true;
+
+end:
+       return err;
+}
+
 static int line6_init_cap_control(struct usb_line6 *line6)
 {
        int ret;
@@ -487,14 +669,20 @@ static int line6_init_cap_control(struct usb_line6 *line6)
        if (!line6->buffer_listen)
                return -ENOMEM;
 
-       line6->buffer_message = kmalloc(LINE6_MESSAGE_MAXLEN, GFP_KERNEL);
-       if (!line6->buffer_message)
-               return -ENOMEM;
-
        line6->urb_listen = usb_alloc_urb(0, GFP_KERNEL);
        if (!line6->urb_listen)
                return -ENOMEM;
 
+       if (line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI) {
+               line6->buffer_message = kmalloc(LINE6_MIDI_MESSAGE_MAXLEN, GFP_KERNEL);
+               if (!line6->buffer_message)
+                       return -ENOMEM;
+       } else {
+               ret = line6_hwdep_init(line6);
+               if (ret < 0)
+                       return ret;
+       }
+
        ret = line6_start_listen(line6);
        if (ret < 0) {
                dev_err(line6->ifcdev, "cannot start listening: %d\n", ret);
@@ -558,6 +746,7 @@ int line6_probe(struct usb_interface *interface,
        /* query interface number */
        interface_number = interface->cur_altsetting->desc.bInterfaceNumber;
 
+       /* TODO reserves the bus bandwidth even without actual transfer */
        ret = usb_set_interface(usbdev, interface_number,
                                properties->altsetting);
        if (ret < 0) {
@@ -565,9 +754,8 @@ int line6_probe(struct usb_interface *interface,
                goto error;
        }
 
-       line6_get_interval(line6);
-
        if (properties->capabilities & LINE6_CAP_CONTROL) {
+               line6_get_interval(line6);
                ret = line6_init_cap_control(line6);
                if (ret < 0)
                        goto error;
@@ -670,3 +858,4 @@ EXPORT_SYMBOL_GPL(line6_resume);
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
+
index 7da643e..7e3a3aa 100644 (file)
 #ifndef DRIVER_H
 #define DRIVER_H
 
-#include <linux/spinlock.h>
 #include <linux/usb.h>
+#include <linux/mutex.h>
+#include <linux/kfifo.h>
 #include <sound/core.h>
 
 #include "midi.h"
 
-#define USB_INTERVALS_PER_SECOND 1000
+/* USB 1.1 speed configuration */
+#define USB_LOW_INTERVALS_PER_SECOND 1000
+#define USB_LOW_ISO_BUFFERS 2
+
+/* USB 2.0+ speed configuration */
+#define USB_HIGH_INTERVALS_PER_SECOND 8000
+#define USB_HIGH_ISO_BUFFERS 16
 
 /* Fallback USB interval and max packet size values */
 #define LINE6_FALLBACK_INTERVAL 10
 #define LINE6_FALLBACK_MAXPACKETSIZE 16
 
 #define LINE6_TIMEOUT 1
-#define LINE6_BUFSIZE_LISTEN 32
-#define LINE6_MESSAGE_MAXLEN 256
+#define LINE6_BUFSIZE_LISTEN 64
+#define LINE6_MIDI_MESSAGE_MAXLEN 256
+
+#define LINE6_RAW_MESSAGES_MAXCOUNT_ORDER 7
+/* 4k packets are common, BUFSIZE * MAXCOUNT should be bigger... */
+#define LINE6_RAW_MESSAGES_MAXCOUNT (1 << LINE6_RAW_MESSAGES_MAXCOUNT_ORDER)
+
+
+#if LINE6_BUFSIZE_LISTEN > 65535
+#error "Use dynamic fifo instead"
+#endif
 
 /*
        Line 6 MIDI control commands
@@ -94,8 +110,12 @@ enum {
        LINE6_CAP_CONTROL =     1 << 0,
        /* device supports PCM input/output via USB */
        LINE6_CAP_PCM =         1 << 1,
-       /* device support hardware monitoring */
+       /* device supports hardware monitoring */
        LINE6_CAP_HWMON =       1 << 2,
+       /* device requires output data when input is read */
+       LINE6_CAP_IN_NEEDS_OUT = 1 << 3,
+       /* device uses raw MIDI via USB (data endpoints) */
+       LINE6_CAP_CONTROL_MIDI = 1 << 4,
 };
 
 /*
@@ -109,10 +129,15 @@ struct usb_line6 {
        /* Properties */
        const struct line6_properties *properties;
 
-       /* Interval (ms) */
+       /* Interval for data USB packets */
        int interval;
+       /* ...for isochronous transfers framing */
+       int intervals_per_second;
+
+       /* Number of isochronous URBs used for frame transfers */
+       int iso_buffers;
 
-       /* Maximum size of USB packet */
+       /* Maximum size of data USB packet */
        int max_packet_size;
 
        /* Device representing the USB interface */
@@ -129,18 +154,30 @@ struct usb_line6 {
        /* Line 6 MIDI device data structure */
        struct snd_line6_midi *line6midi;
 
-       /* URB for listening to PODxt Pro control endpoint */
+       /* URB for listening to POD data endpoint */
        struct urb *urb_listen;
 
-       /* Buffer for listening to PODxt Pro control endpoint */
+       /* Buffer for incoming data from POD data endpoint */
        unsigned char *buffer_listen;
 
-       /* Buffer for message to be processed */
+       /* Buffer for message to be processed, generated from MIDI layer */
        unsigned char *buffer_message;
 
-       /* Length of message to be processed */
+       /* Length of message to be processed, generated from MIDI layer  */
        int message_length;
 
+       /* Circular buffer for non-MIDI control messages */
+       struct {
+               struct mutex read_lock;
+               wait_queue_head_t wait_queue;
+               unsigned int active:1;
+               STRUCT_KFIFO_REC_2(LINE6_BUFSIZE_LISTEN * LINE6_RAW_MESSAGES_MAXCOUNT)
+                       fifo;
+       } messages;
+
+       /* If MIDI is supported, buffer_message contains the pre-processed data;
+        * otherwise the data is only in urb_listen (buffer_incoming).
+        */
        void (*process_message)(struct usb_line6 *);
        void (*disconnect)(struct usb_line6 *line6);
 };
index cebea9b..d0fb2f2 100644 (file)
@@ -258,7 +258,7 @@ int line6_init_midi(struct usb_line6 *line6)
        struct snd_rawmidi *rmidi;
        struct snd_line6_midi *line6midi;
 
-       if (!(line6->properties->capabilities & LINE6_CAP_CONTROL)) {
+       if (!(line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI)) {
                /* skip MIDI initialization and report success */
                return 0;
        }
index 41aa335..fab53f5 100644 (file)
@@ -52,7 +52,7 @@ static int snd_line6_impulse_volume_put(struct snd_kcontrol *kcontrol,
 
        line6pcm->impulse_volume = value;
        if (value > 0) {
-               err = line6_pcm_acquire(line6pcm, LINE6_STREAM_IMPULSE);
+               err = line6_pcm_acquire(line6pcm, LINE6_STREAM_IMPULSE, true);
                if (err < 0) {
                        line6pcm->impulse_volume = 0;
                        return err;
@@ -104,7 +104,7 @@ static void line6_unlink_audio_urbs(struct snd_line6_pcm *line6pcm,
 {
        int i;
 
-       for (i = 0; i < LINE6_ISO_BUFFERS; i++) {
+       for (i = 0; i < line6pcm->line6->iso_buffers; i++) {
                if (test_bit(i, &pcms->active_urbs)) {
                        if (!test_and_set_bit(i, &pcms->unlink_urbs))
                                usb_unlink_urb(pcms->urbs[i]);
@@ -124,7 +124,7 @@ static void line6_wait_clear_audio_urbs(struct snd_line6_pcm *line6pcm,
 
        do {
                alive = 0;
-               for (i = 0; i < LINE6_ISO_BUFFERS; i++) {
+               for (i = 0; i < line6pcm->line6->iso_buffers; i++) {
                        if (test_bit(i, &pcms->active_urbs))
                                alive++;
                }
@@ -146,15 +146,20 @@ get_stream(struct snd_line6_pcm *line6pcm, int direction)
 }
 
 /* allocate a buffer if not opened yet;
- * call this in line6pcm.state_change mutex
+ * call this in line6pcm.state_mutex
  */
 static int line6_buffer_acquire(struct snd_line6_pcm *line6pcm,
-                               struct line6_pcm_stream *pstr, int type)
+                               struct line6_pcm_stream *pstr, int direction, int type)
 {
+       const int pkt_size =
+               (direction == SNDRV_PCM_STREAM_PLAYBACK) ?
+                       line6pcm->max_packet_size_out :
+                       line6pcm->max_packet_size_in;
+
        /* Invoked multiple times in a row so allocate once only */
        if (!test_and_set_bit(type, &pstr->opened) && !pstr->buffer) {
-               pstr->buffer = kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS *
-                                      line6pcm->max_packet_size, GFP_KERNEL);
+               pstr->buffer = kmalloc(line6pcm->line6->iso_buffers *
+                                      LINE6_ISO_PACKETS * pkt_size, GFP_KERNEL);
                if (!pstr->buffer)
                        return -ENOMEM;
        }
@@ -162,12 +167,11 @@ static int line6_buffer_acquire(struct snd_line6_pcm *line6pcm,
 }
 
 /* free a buffer if all streams are closed;
- * call this in line6pcm.state_change mutex
+ * call this in line6pcm.state_mutex
  */
 static void line6_buffer_release(struct snd_line6_pcm *line6pcm,
                                 struct line6_pcm_stream *pstr, int type)
 {
-
        clear_bit(type, &pstr->opened);
        if (!pstr->opened) {
                line6_wait_clear_audio_urbs(line6pcm, pstr);
@@ -194,6 +198,7 @@ static int line6_stream_start(struct snd_line6_pcm *line6pcm, int direction,
                else
                        ret = line6_submit_audio_in_all_urbs(line6pcm);
        }
+
        if (ret < 0)
                clear_bit(type, &pstr->running);
        spin_unlock_irqrestore(&pstr->lock, flags);
@@ -237,6 +242,14 @@ int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd)
                switch (cmd) {
                case SNDRV_PCM_TRIGGER_START:
                case SNDRV_PCM_TRIGGER_RESUME:
+                       if (s->stream == SNDRV_PCM_STREAM_CAPTURE &&
+                               (line6pcm->line6->properties->capabilities &
+                                       LINE6_CAP_IN_NEEDS_OUT)) {
+                               err = line6_stream_start(line6pcm, SNDRV_PCM_STREAM_PLAYBACK,
+                                                LINE6_STREAM_CAPTURE_HELPER);
+                               if (err < 0)
+                                       return err;
+                       }
                        err = line6_stream_start(line6pcm, s->stream,
                                                 LINE6_STREAM_PCM);
                        if (err < 0)
@@ -245,6 +258,12 @@ int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd)
 
                case SNDRV_PCM_TRIGGER_STOP:
                case SNDRV_PCM_TRIGGER_SUSPEND:
+                       if (s->stream == SNDRV_PCM_STREAM_CAPTURE &&
+                               (line6pcm->line6->properties->capabilities &
+                                       LINE6_CAP_IN_NEEDS_OUT)) {
+                               line6_stream_stop(line6pcm, SNDRV_PCM_STREAM_PLAYBACK,
+                                         LINE6_STREAM_CAPTURE_HELPER);
+                       }
                        line6_stream_stop(line6pcm, s->stream,
                                          LINE6_STREAM_PCM);
                        break;
@@ -278,27 +297,30 @@ snd_pcm_uframes_t snd_line6_pointer(struct snd_pcm_substream *substream)
        return pstr->pos_done;
 }
 
-/* Acquire and start duplex streams:
+/* Acquire and optionally start duplex streams:
  * type is either LINE6_STREAM_IMPULSE or LINE6_STREAM_MONITOR
  */
-int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type)
+int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type, bool start)
 {
        struct line6_pcm_stream *pstr;
        int ret = 0, dir;
 
+       /* TODO: We should assert SNDRV_PCM_STREAM_PLAYBACK/CAPTURE == 0/1 */
        mutex_lock(&line6pcm->state_mutex);
        for (dir = 0; dir < 2; dir++) {
                pstr = get_stream(line6pcm, dir);
-               ret = line6_buffer_acquire(line6pcm, pstr, type);
+               ret = line6_buffer_acquire(line6pcm, pstr, dir, type);
                if (ret < 0)
                        goto error;
                if (!pstr->running)
                        line6_wait_clear_audio_urbs(line6pcm, pstr);
        }
-       for (dir = 0; dir < 2; dir++) {
-               ret = line6_stream_start(line6pcm, dir, type);
-               if (ret < 0)
-                       goto error;
+       if (start) {
+               for (dir = 0; dir < 2; dir++) {
+                       ret = line6_stream_start(line6pcm, dir, type);
+                       if (ret < 0)
+                               goto error;
+               }
        }
  error:
        mutex_unlock(&line6pcm->state_mutex);
@@ -334,7 +356,8 @@ int snd_line6_hw_params(struct snd_pcm_substream *substream,
        struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream);
 
        mutex_lock(&line6pcm->state_mutex);
-       ret = line6_buffer_acquire(line6pcm, pstr, LINE6_STREAM_PCM);
+       ret = line6_buffer_acquire(line6pcm, pstr, substream->stream,
+                                  LINE6_STREAM_PCM);
        if (ret < 0)
                goto error;
 
@@ -434,24 +457,30 @@ static struct snd_kcontrol_new line6_controls[] = {
 /*
        Cleanup the PCM device.
 */
-static void cleanup_urbs(struct line6_pcm_stream *pcms)
+static void cleanup_urbs(struct line6_pcm_stream *pcms, int iso_buffers)
 {
        int i;
 
-       for (i = 0; i < LINE6_ISO_BUFFERS; i++) {
+       /* Most likely impossible in current code... */
+       if (pcms->urbs == NULL)
+               return;
+
+       for (i = 0; i < iso_buffers; i++) {
                if (pcms->urbs[i]) {
                        usb_kill_urb(pcms->urbs[i]);
                        usb_free_urb(pcms->urbs[i]);
                }
        }
+       kfree(pcms->urbs);
+       pcms->urbs = NULL;
 }
 
 static void line6_cleanup_pcm(struct snd_pcm *pcm)
 {
        struct snd_line6_pcm *line6pcm = snd_pcm_chip(pcm);
 
-       cleanup_urbs(&line6pcm->out);
-       cleanup_urbs(&line6pcm->in);
+       cleanup_urbs(&line6pcm->out, line6pcm->line6->iso_buffers);
+       cleanup_urbs(&line6pcm->in, line6pcm->line6->iso_buffers);
        kfree(line6pcm);
 }
 
@@ -523,12 +552,12 @@ int line6_init_pcm(struct usb_line6 *line6,
        line6pcm->volume_monitor = 255;
        line6pcm->line6 = line6;
 
-       /* Read and write buffers are sized identically, so choose minimum */
-       line6pcm->max_packet_size = min(
-                       usb_maxpacket(line6->usbdev,
-                               usb_rcvisocpipe(line6->usbdev, ep_read), 0),
-                       usb_maxpacket(line6->usbdev,
-                               usb_sndisocpipe(line6->usbdev, ep_write), 1));
+       line6pcm->max_packet_size_in =
+               usb_maxpacket(line6->usbdev,
+                       usb_rcvisocpipe(line6->usbdev, ep_read), 0);
+       line6pcm->max_packet_size_out =
+               usb_maxpacket(line6->usbdev,
+                       usb_sndisocpipe(line6->usbdev, ep_write), 1);
 
        spin_lock_init(&line6pcm->out.lock);
        spin_lock_init(&line6pcm->in.lock);
index 508410a..bb0c9cb 100644 (file)
@@ -20,9 +20,6 @@
 
 #include "driver.h"
 
-/* number of URBs */
-#define LINE6_ISO_BUFFERS      2
-
 /*
        number of USB frames per URB
        The Line 6 Windows driver always transmits two frames per packet, but
@@ -31,7 +28,9 @@
 */
 #define LINE6_ISO_PACKETS      1
 
-/* in a "full speed" device (such as the PODxt Pro) this means 1ms */
+/* in a "full speed" device (such as the PODxt Pro) this means 1ms,
+ *  for "high speed" it's 1/8ms
+ */
 #define LINE6_ISO_INTERVAL     1
 
 #define LINE6_IMPULSE_DEFAULT_PERIOD 100
@@ -74,6 +73,7 @@ enum {
        LINE6_STREAM_PCM,
        LINE6_STREAM_MONITOR,
        LINE6_STREAM_IMPULSE,
+       LINE6_STREAM_CAPTURE_HELPER,
 };
 
 /* misc bit flags for PCM operation */
@@ -85,12 +85,12 @@ enum {
 struct line6_pcm_properties {
        struct snd_pcm_hardware playback_hw, capture_hw;
        struct snd_pcm_hw_constraint_ratdens rates;
-       int bytes_per_frame;
+       int bytes_per_channel;
 };
 
 struct line6_pcm_stream {
        /* allocated URBs */
-       struct urb *urbs[LINE6_ISO_BUFFERS];
+       struct urb **urbs;
 
        /* Temporary buffer;
         * Since the packet size is not known in advance, this buffer is
@@ -157,11 +157,12 @@ struct snd_line6_pcm {
        /* Previously captured frame (for software monitoring) */
        unsigned char *prev_fbuf;
 
-       /* Size of previously captured frame (for software monitoring) */
+       /* Size of previously captured frame (for software monitoring/sync) */
        int prev_fsize;
 
        /* Maximum size of USB packet */
-       int max_packet_size;
+       int max_packet_size_in;
+       int max_packet_size_out;
 
        /* PCM playback volume (left and right) */
        int volume_playback[2];
@@ -191,7 +192,8 @@ extern int snd_line6_hw_params(struct snd_pcm_substream *substream,
 extern int snd_line6_hw_free(struct snd_pcm_substream *substream);
 extern snd_pcm_uframes_t snd_line6_pointer(struct snd_pcm_substream *substream);
 extern void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm);
-extern int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type);
+extern int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type,
+                              bool start);
 extern void line6_pcm_release(struct snd_line6_pcm *line6pcm, int type);
 
 #endif
index 97ed593..812d181 100644 (file)
@@ -146,18 +146,20 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm)
        int index;
        int i, urb_size, urb_frames;
        int ret;
-       const int bytes_per_frame = line6pcm->properties->bytes_per_frame;
+       const int bytes_per_frame =
+               line6pcm->properties->bytes_per_channel *
+               line6pcm->properties->playback_hw.channels_max;
        const int frame_increment =
                line6pcm->properties->rates.rats[0].num_min;
        const int frame_factor =
                line6pcm->properties->rates.rats[0].den *
-               (USB_INTERVALS_PER_SECOND / LINE6_ISO_INTERVAL);
+               (line6pcm->line6->intervals_per_second / LINE6_ISO_INTERVAL);
        struct urb *urb_out;
 
-       index =
-           find_first_zero_bit(&line6pcm->out.active_urbs, LINE6_ISO_BUFFERS);
+       index = find_first_zero_bit(&line6pcm->out.active_urbs,
+                                   line6pcm->line6->iso_buffers);
 
-       if (index < 0 || index >= LINE6_ISO_BUFFERS) {
+       if (index < 0 || index >= line6pcm->line6->iso_buffers) {
                dev_err(line6pcm->line6->ifcdev, "no free URB found\n");
                return -EINVAL;
        }
@@ -165,6 +167,7 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm)
        urb_out = line6pcm->out.urbs[index];
        urb_size = 0;
 
+       /* TODO: this may not work for LINE6_ISO_PACKETS != 1 */
        for (i = 0; i < LINE6_ISO_PACKETS; ++i) {
                /* compute frame size for given sampling rate */
                int fsize = 0;
@@ -178,9 +181,11 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm)
                        line6pcm->out.count += frame_increment;
                        n = line6pcm->out.count / frame_factor;
                        line6pcm->out.count -= n * frame_factor;
-                       fsize = n * bytes_per_frame;
+                       fsize = n;
                }
 
+               fsize *= bytes_per_frame;
+
                fout->offset = urb_size;
                fout->length = fsize;
                urb_size += fsize;
@@ -195,7 +200,7 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm)
        urb_frames = urb_size / bytes_per_frame;
        urb_out->transfer_buffer =
            line6pcm->out.buffer +
-           index * LINE6_ISO_PACKETS * line6pcm->max_packet_size;
+           index * LINE6_ISO_PACKETS * line6pcm->max_packet_size_out;
        urb_out->transfer_buffer_length = urb_size;
        urb_out->context = line6pcm;
 
@@ -286,7 +291,7 @@ int line6_submit_audio_out_all_urbs(struct snd_line6_pcm *line6pcm)
 {
        int ret = 0, i;
 
-       for (i = 0; i < LINE6_ISO_BUFFERS; ++i) {
+       for (i = 0; i < line6pcm->line6->iso_buffers; ++i) {
                ret = submit_audio_out_urb(line6pcm);
                if (ret < 0)
                        break;
@@ -305,6 +310,9 @@ static void audio_out_callback(struct urb *urb)
        struct snd_line6_pcm *line6pcm = (struct snd_line6_pcm *)urb->context;
        struct snd_pcm_substream *substream =
            get_substream(line6pcm, SNDRV_PCM_STREAM_PLAYBACK);
+       const int bytes_per_frame =
+               line6pcm->properties->bytes_per_channel *
+               line6pcm->properties->playback_hw.channels_max;
 
 #if USE_CLEAR_BUFFER_WORKAROUND
        memset(urb->transfer_buffer, 0, urb->transfer_buffer_length);
@@ -313,11 +321,11 @@ static void audio_out_callback(struct urb *urb)
        line6pcm->out.last_frame = urb->start_frame;
 
        /* find index of URB */
-       for (index = 0; index < LINE6_ISO_BUFFERS; index++)
+       for (index = 0; index < line6pcm->line6->iso_buffers; index++)
                if (urb == line6pcm->out.urbs[index])
                        break;
 
-       if (index >= LINE6_ISO_BUFFERS)
+       if (index >= line6pcm->line6->iso_buffers)
                return;         /* URB has been unlinked asynchronously */
 
        for (i = 0; i < LINE6_ISO_PACKETS; i++)
@@ -329,7 +337,7 @@ static void audio_out_callback(struct urb *urb)
                struct snd_pcm_runtime *runtime = substream->runtime;
 
                line6pcm->out.pos_done +=
-                   length / line6pcm->properties->bytes_per_frame;
+                   length / bytes_per_frame;
 
                if (line6pcm->out.pos_done >= runtime->buffer_size)
                        line6pcm->out.pos_done -= runtime->buffer_size;
@@ -401,8 +409,13 @@ int line6_create_audio_out_urbs(struct snd_line6_pcm *line6pcm)
        struct usb_line6 *line6 = line6pcm->line6;
        int i;
 
+       line6pcm->out.urbs = kzalloc(
+               sizeof(struct urb *) * line6->iso_buffers, GFP_KERNEL);
+       if (line6pcm->out.urbs == NULL)
+               return -ENOMEM;
+
        /* create audio URBs and fill in constant values: */
-       for (i = 0; i < LINE6_ISO_BUFFERS; ++i) {
+       for (i = 0; i < line6->iso_buffers; ++i) {
                struct urb *urb;
 
                /* URB for audio out: */
index 45dd348..17aa616 100644 (file)
@@ -83,7 +83,6 @@ struct usb_line6_pod {
 };
 
 #define POD_SYSEX_CODE 3
-#define POD_BYTES_PER_FRAME 6  /* 24bit audio (stereo) */
 
 /* *INDENT-OFF* */
 
@@ -167,7 +166,7 @@ static struct line6_pcm_properties pod_pcm_properties = {
        .rates = {
                            .nrats = 1,
                            .rats = &pod_ratden},
-       .bytes_per_frame = POD_BYTES_PER_FRAME
+       .bytes_per_channel = 3 /* SNDRV_PCM_FMTBIT_S24_3LE */
 };
 
 static const char pod_version_header[] = {
@@ -476,6 +475,7 @@ static const struct line6_properties pod_properties_table[] = {
                .id = "BassPODxt",
                .name = "BassPODxt",
                .capabilities   = LINE6_CAP_CONTROL
+                               | LINE6_CAP_CONTROL_MIDI
                                | LINE6_CAP_PCM
                                | LINE6_CAP_HWMON,
                .altsetting = 5,
@@ -488,6 +488,7 @@ static const struct line6_properties pod_properties_table[] = {
                .id = "BassPODxtLive",
                .name = "BassPODxt Live",
                .capabilities   = LINE6_CAP_CONTROL
+                               | LINE6_CAP_CONTROL_MIDI
                                | LINE6_CAP_PCM
                                | LINE6_CAP_HWMON,
                .altsetting = 1,
@@ -500,6 +501,7 @@ static const struct line6_properties pod_properties_table[] = {
                .id = "BassPODxtPro",
                .name = "BassPODxt Pro",
                .capabilities   = LINE6_CAP_CONTROL
+                               | LINE6_CAP_CONTROL_MIDI
                                | LINE6_CAP_PCM
                                | LINE6_CAP_HWMON,
                .altsetting = 5,
@@ -511,7 +513,8 @@ static const struct line6_properties pod_properties_table[] = {
        [LINE6_POCKETPOD] = {
                .id = "PocketPOD",
                .name = "Pocket POD",
-               .capabilities   = LINE6_CAP_CONTROL,
+               .capabilities   = LINE6_CAP_CONTROL
+                               | LINE6_CAP_CONTROL_MIDI,
                .altsetting = 0,
                .ep_ctrl_r = 0x82,
                .ep_ctrl_w = 0x02,
@@ -521,6 +524,7 @@ static const struct line6_properties pod_properties_table[] = {
                .id = "PODxt",
                .name = "PODxt",
                .capabilities   = LINE6_CAP_CONTROL
+                               | LINE6_CAP_CONTROL_MIDI
                                | LINE6_CAP_PCM
                                | LINE6_CAP_HWMON,
                .altsetting = 5,
@@ -533,6 +537,7 @@ static const struct line6_properties pod_properties_table[] = {
                .id = "PODxtLive",
                .name = "PODxt Live",
                .capabilities   = LINE6_CAP_CONTROL
+                               | LINE6_CAP_CONTROL_MIDI
                                | LINE6_CAP_PCM
                                | LINE6_CAP_HWMON,
                .altsetting = 1,
@@ -545,6 +550,7 @@ static const struct line6_properties pod_properties_table[] = {
                .id = "PODxtPro",
                .name = "PODxt Pro",
                .capabilities   = LINE6_CAP_CONTROL
+                               | LINE6_CAP_CONTROL_MIDI
                                | LINE6_CAP_PCM
                                | LINE6_CAP_HWMON,
                .altsetting = 5,
index 63dcaef..9352a44 100644 (file)
@@ -2,6 +2,7 @@
  * Line 6 Pod HD
  *
  * Copyright (C) 2011 Stefan Hajnoczi <stefanha@gmail.com>
+ * Copyright (C) 2015 Andrej Krutak <dev@andree.sk>
  *
  *     This program is free software; you can redistribute it and/or
  *     modify it under the terms of the GNU General Public License as
 #include "driver.h"
 #include "pcm.h"
 
+#define PODHD_STARTUP_DELAY 500
+
+/*
+ * Stages of POD startup procedure
+ */
+enum {
+       PODHD_STARTUP_INIT = 1,
+       PODHD_STARTUP_SCHEDULE_WORKQUEUE,
+       PODHD_STARTUP_SETUP,
+       PODHD_STARTUP_LAST = PODHD_STARTUP_SETUP - 1
+};
+
 enum {
        LINE6_PODHD300,
        LINE6_PODHD400,
        LINE6_PODHD500_0,
        LINE6_PODHD500_1,
+       LINE6_PODX3,
+       LINE6_PODX3LIVE
 };
 
-#define PODHD_BYTES_PER_FRAME 6        /* 24bit audio (stereo) */
+struct usb_line6_podhd {
+       /* Generic Line 6 USB data */
+       struct usb_line6 line6;
+
+       /* Timer for device initialization */
+       struct timer_list startup_timer;
+
+       /* Work handler for device initialization */
+       struct work_struct startup_work;
+
+       /* Current progress in startup procedure */
+       int startup_progress;
+
+       /* Serial number of device */
+       u32 serial_number;
+
+       /* Firmware version */
+       int firmware_version;
+};
 
 static struct snd_ratden podhd_ratden = {
        .num_min = 48000,
@@ -73,9 +106,196 @@ static struct line6_pcm_properties podhd_pcm_properties = {
        .rates = {
                            .nrats = 1,
                            .rats = &podhd_ratden},
-       .bytes_per_frame = PODHD_BYTES_PER_FRAME
+       .bytes_per_channel = 3 /* SNDRV_PCM_FMTBIT_S24_3LE */
+};
+
+static struct line6_pcm_properties podx3_pcm_properties = {
+       .playback_hw = {
+                                 .info = (SNDRV_PCM_INFO_MMAP |
+                                          SNDRV_PCM_INFO_INTERLEAVED |
+                                          SNDRV_PCM_INFO_BLOCK_TRANSFER |
+                                          SNDRV_PCM_INFO_MMAP_VALID |
+                                          SNDRV_PCM_INFO_PAUSE |
+                                          SNDRV_PCM_INFO_SYNC_START),
+                                 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                 .rates = SNDRV_PCM_RATE_48000,
+                                 .rate_min = 48000,
+                                 .rate_max = 48000,
+                                 .channels_min = 2,
+                                 .channels_max = 2,
+                                 .buffer_bytes_max = 60000,
+                                 .period_bytes_min = 64,
+                                 .period_bytes_max = 8192,
+                                 .periods_min = 1,
+                                 .periods_max = 1024},
+       .capture_hw = {
+                                .info = (SNDRV_PCM_INFO_MMAP |
+                                         SNDRV_PCM_INFO_INTERLEAVED |
+                                         SNDRV_PCM_INFO_BLOCK_TRANSFER |
+                                         SNDRV_PCM_INFO_MMAP_VALID |
+                                         SNDRV_PCM_INFO_SYNC_START),
+                                .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                .rates = SNDRV_PCM_RATE_48000,
+                                .rate_min = 48000,
+                                .rate_max = 48000,
+                                /* 1+2: Main signal (out), 3+4: Tone 1,
+                                 * 5+6: Tone 2, 7+8: raw
+                                 */
+                                .channels_min = 8,
+                                .channels_max = 8,
+                                .buffer_bytes_max = 60000,
+                                .period_bytes_min = 64,
+                                .period_bytes_max = 8192,
+                                .periods_min = 1,
+                                .periods_max = 1024},
+       .rates = {
+                           .nrats = 1,
+                           .rats = &podhd_ratden},
+       .bytes_per_channel = 3 /* SNDRV_PCM_FMTBIT_S24_3LE */
+};
+
+static void podhd_startup_start_workqueue(unsigned long data);
+static void podhd_startup_workqueue(struct work_struct *work);
+static int podhd_startup_finalize(struct usb_line6_podhd *pod);
+
+static ssize_t serial_number_show(struct device *dev,
+                                 struct device_attribute *attr, char *buf)
+{
+       struct snd_card *card = dev_to_snd_card(dev);
+       struct usb_line6_podhd *pod = card->private_data;
+
+       return sprintf(buf, "%u\n", pod->serial_number);
+}
+
+static ssize_t firmware_version_show(struct device *dev,
+                                    struct device_attribute *attr, char *buf)
+{
+       struct snd_card *card = dev_to_snd_card(dev);
+       struct usb_line6_podhd *pod = card->private_data;
+
+       return sprintf(buf, "%06x\n", pod->firmware_version);
+}
+
+static DEVICE_ATTR_RO(firmware_version);
+static DEVICE_ATTR_RO(serial_number);
+
+static struct attribute *podhd_dev_attrs[] = {
+       &dev_attr_firmware_version.attr,
+       &dev_attr_serial_number.attr,
+       NULL
+};
+
+static const struct attribute_group podhd_dev_attr_group = {
+       .name = "podhd",
+       .attrs = podhd_dev_attrs,
 };
 
+/*
+ * POD X3 startup procedure.
+ *
+ * May be compatible with other POD HD's, since it's also similar to the
+ * previous POD setup. In any case, it doesn't seem to be required for the
+ * audio nor bulk interfaces to work.
+ */
+
+static void podhd_startup(struct usb_line6_podhd *pod)
+{
+       CHECK_STARTUP_PROGRESS(pod->startup_progress, PODHD_STARTUP_INIT);
+
+       /* delay startup procedure: */
+       line6_start_timer(&pod->startup_timer, PODHD_STARTUP_DELAY,
+               podhd_startup_start_workqueue, (unsigned long)pod);
+}
+
+static void podhd_startup_start_workqueue(unsigned long data)
+{
+       struct usb_line6_podhd *pod = (struct usb_line6_podhd *)data;
+
+       CHECK_STARTUP_PROGRESS(pod->startup_progress,
+               PODHD_STARTUP_SCHEDULE_WORKQUEUE);
+
+       /* schedule work for global work queue: */
+       schedule_work(&pod->startup_work);
+}
+
+static int podhd_dev_start(struct usb_line6_podhd *pod)
+{
+       int ret;
+       u8 init_bytes[8];
+       int i;
+       struct usb_device *usbdev = pod->line6.usbdev;
+
+       ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0),
+                                       0x67, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
+                                       0x11, 0,
+                                       NULL, 0, LINE6_TIMEOUT * HZ);
+       if (ret < 0) {
+               dev_err(pod->line6.ifcdev, "read request failed (error %d)\n", ret);
+               return ret;
+       }
+
+       /* NOTE: looks like some kind of ping message */
+       ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), 0x67,
+                                       USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
+                                       0x11, 0x0,
+                                       &init_bytes, 3, LINE6_TIMEOUT * HZ);
+       if (ret < 0) {
+               dev_err(pod->line6.ifcdev,
+                       "receive length failed (error %d)\n", ret);
+               return ret;
+       }
+
+       pod->firmware_version =
+               (init_bytes[0] << 16) | (init_bytes[1] << 8) | (init_bytes[2] << 0);
+
+       for (i = 0; i <= 16; i++) {
+               ret = line6_read_data(&pod->line6, 0xf000 + 0x08 * i, init_bytes, 8);
+               if (ret < 0)
+                       return ret;
+       }
+
+       ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0),
+                                       USB_REQ_SET_FEATURE,
+                                       USB_TYPE_STANDARD | USB_RECIP_DEVICE | USB_DIR_OUT,
+                                       1, 0,
+                                       NULL, 0, LINE6_TIMEOUT * HZ);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+static void podhd_startup_workqueue(struct work_struct *work)
+{
+       struct usb_line6_podhd *pod =
+           container_of(work, struct usb_line6_podhd, startup_work);
+
+       CHECK_STARTUP_PROGRESS(pod->startup_progress, PODHD_STARTUP_SETUP);
+
+       podhd_dev_start(pod);
+       line6_read_serial_number(&pod->line6, &pod->serial_number);
+
+       podhd_startup_finalize(pod);
+}
+
+static int podhd_startup_finalize(struct usb_line6_podhd *pod)
+{
+       struct usb_line6 *line6 = &pod->line6;
+
+       /* ALSA audio interface: */
+       return snd_card_register(line6->card);
+}
+
+static void podhd_disconnect(struct usb_line6 *line6)
+{
+       struct usb_line6_podhd *pod = (struct usb_line6_podhd *)line6;
+
+       if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL) {
+               del_timer_sync(&pod->startup_timer);
+               cancel_work_sync(&pod->startup_work);
+       }
+}
+
 /*
        Try to init POD HD device.
 */
@@ -83,19 +303,36 @@ static int podhd_init(struct usb_line6 *line6,
                      const struct usb_device_id *id)
 {
        int err;
+       struct usb_line6_podhd *pod = (struct usb_line6_podhd *) line6;
 
-       /* initialize MIDI subsystem: */
-       err = line6_init_midi(line6);
-       if (err < 0)
-               return err;
+       line6->disconnect = podhd_disconnect;
 
-       /* initialize PCM subsystem: */
-       err = line6_init_pcm(line6, &podhd_pcm_properties);
-       if (err < 0)
-               return err;
+       if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL) {
+               /* create sysfs entries: */
+               err = snd_card_add_dev_attr(line6->card, &podhd_dev_attr_group);
+               if (err < 0)
+                       return err;
+       }
 
-       /* register USB audio system: */
-       return snd_card_register(line6->card);
+       if (pod->line6.properties->capabilities & LINE6_CAP_PCM) {
+               /* initialize PCM subsystem: */
+               err = line6_init_pcm(line6,
+                       (id->driver_info == LINE6_PODX3) ? &podx3_pcm_properties :
+                       &podhd_pcm_properties);
+               if (err < 0)
+                       return err;
+       }
+
+       if (!(pod->line6.properties->capabilities & LINE6_CAP_CONTROL)) {
+               /* register USB audio system directly */
+               return podhd_startup_finalize(pod);
+       }
+
+       /* init device and delay registering */
+       init_timer(&pod->startup_timer);
+       INIT_WORK(&pod->startup_work, podhd_startup_workqueue);
+       podhd_startup(pod);
+       return 0;
 }
 
 #define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod)
@@ -103,10 +340,13 @@ static int podhd_init(struct usb_line6 *line6,
 
 /* table of devices that work with this driver */
 static const struct usb_device_id podhd_id_table[] = {
+       /* TODO: no need to alloc data interfaces when only audio is used */
        { LINE6_DEVICE(0x5057),    .driver_info = LINE6_PODHD300 },
        { LINE6_DEVICE(0x5058),    .driver_info = LINE6_PODHD400 },
        { LINE6_IF_NUM(0x414D, 0), .driver_info = LINE6_PODHD500_0 },
        { LINE6_IF_NUM(0x414D, 1), .driver_info = LINE6_PODHD500_1 },
+       { LINE6_IF_NUM(0x414A, 0), .driver_info = LINE6_PODX3 },
+       { LINE6_IF_NUM(0x414B, 0), .driver_info = LINE6_PODX3LIVE },
        {}
 };
 
@@ -116,8 +356,7 @@ static const struct line6_properties podhd_properties_table[] = {
        [LINE6_PODHD300] = {
                .id = "PODHD300",
                .name = "POD HD300",
-               .capabilities   = LINE6_CAP_CONTROL
-                               | LINE6_CAP_PCM
+               .capabilities   = LINE6_CAP_PCM
                                | LINE6_CAP_HWMON,
                .altsetting = 5,
                .ep_ctrl_r = 0x84,
@@ -128,8 +367,7 @@ static const struct line6_properties podhd_properties_table[] = {
        [LINE6_PODHD400] = {
                .id = "PODHD400",
                .name = "POD HD400",
-               .capabilities   = LINE6_CAP_CONTROL
-                               | LINE6_CAP_PCM
+               .capabilities   = LINE6_CAP_PCM
                                | LINE6_CAP_HWMON,
                .altsetting = 5,
                .ep_ctrl_r = 0x84,
@@ -140,8 +378,7 @@ static const struct line6_properties podhd_properties_table[] = {
        [LINE6_PODHD500_0] = {
                .id = "PODHD500",
                .name = "POD HD500",
-               .capabilities   = LINE6_CAP_CONTROL
-                               | LINE6_CAP_PCM
+               .capabilities   = LINE6_CAP_PCM
                                | LINE6_CAP_HWMON,
                .altsetting = 1,
                .ep_ctrl_r = 0x81,
@@ -152,8 +389,7 @@ static const struct line6_properties podhd_properties_table[] = {
        [LINE6_PODHD500_1] = {
                .id = "PODHD500",
                .name = "POD HD500",
-               .capabilities   = LINE6_CAP_CONTROL
-                               | LINE6_CAP_PCM
+               .capabilities   = LINE6_CAP_PCM
                                | LINE6_CAP_HWMON,
                .altsetting = 1,
                .ep_ctrl_r = 0x81,
@@ -161,6 +397,28 @@ static const struct line6_properties podhd_properties_table[] = {
                .ep_audio_r = 0x86,
                .ep_audio_w = 0x02,
        },
+       [LINE6_PODX3] = {
+               .id = "PODX3",
+               .name = "POD X3",
+               .capabilities   = LINE6_CAP_CONTROL
+                               | LINE6_CAP_PCM | LINE6_CAP_HWMON | LINE6_CAP_IN_NEEDS_OUT,
+               .altsetting = 1,
+               .ep_ctrl_r = 0x81,
+               .ep_ctrl_w = 0x01,
+               .ep_audio_r = 0x86,
+               .ep_audio_w = 0x02,
+       },
+       [LINE6_PODX3LIVE] = {
+               .id = "PODX3LIVE",
+               .name = "POD X3 LIVE",
+               .capabilities   = LINE6_CAP_CONTROL
+                               | LINE6_CAP_PCM | LINE6_CAP_HWMON | LINE6_CAP_IN_NEEDS_OUT,
+               .altsetting = 1,
+               .ep_ctrl_r = 0x81,
+               .ep_ctrl_w = 0x01,
+               .ep_audio_r = 0x86,
+               .ep_audio_w = 0x02,
+       },
 };
 
 /*
@@ -171,7 +429,7 @@ static int podhd_probe(struct usb_interface *interface,
 {
        return line6_probe(interface, id, "Line6-PODHD",
                           &podhd_properties_table[id->driver_info],
-                          podhd_init, sizeof(struct usb_line6));
+                          podhd_init, sizeof(struct usb_line6_podhd));
 }
 
 static struct usb_driver podhd_driver = {
index 6d4c50c..8e22f43 100644 (file)
@@ -114,7 +114,7 @@ static struct line6_pcm_properties toneport_pcm_properties = {
        .rates = {
                            .nrats = 1,
                            .rats = &toneport_ratden},
-       .bytes_per_frame = 4
+       .bytes_per_channel = 2
 };
 
 static const struct {
@@ -177,7 +177,7 @@ static int snd_toneport_monitor_put(struct snd_kcontrol *kcontrol,
        line6pcm->volume_monitor = ucontrol->value.integer.value[0];
 
        if (line6pcm->volume_monitor > 0) {
-               err = line6_pcm_acquire(line6pcm, LINE6_STREAM_MONITOR);
+               err = line6_pcm_acquire(line6pcm, LINE6_STREAM_MONITOR, true);
                if (err < 0) {
                        line6pcm->volume_monitor = 0;
                        line6_pcm_release(line6pcm, LINE6_STREAM_MONITOR);
@@ -246,7 +246,7 @@ static void toneport_start_pcm(unsigned long arg)
        struct usb_line6_toneport *toneport = (struct usb_line6_toneport *)arg;
        struct usb_line6 *line6 = &toneport->line6;
 
-       line6_pcm_acquire(line6->line6pcm, LINE6_STREAM_MONITOR);
+       line6_pcm_acquire(line6->line6pcm, LINE6_STREAM_MONITOR, true);
 }
 
 /* control definition */
index ddc23dd..0c4512d 100644 (file)
@@ -259,7 +259,8 @@ static const struct line6_properties variax_properties_table[] = {
        [LINE6_PODXTLIVE_VARIAX] = {
                .id = "PODxtLive",
                .name = "PODxt Live",
-               .capabilities   = LINE6_CAP_CONTROL,
+               .capabilities   = LINE6_CAP_CONTROL
+                               | LINE6_CAP_CONTROL_MIDI,
                .altsetting = 1,
                .ep_ctrl_r = 0x86,
                .ep_ctrl_w = 0x05,
@@ -269,7 +270,8 @@ static const struct line6_properties variax_properties_table[] = {
        [LINE6_VARIAX] = {
                .id = "Variax",
                .name = "Variax Workbench",
-               .capabilities   = LINE6_CAP_CONTROL,
+               .capabilities   = LINE6_CAP_CONTROL
+                               | LINE6_CAP_CONTROL_MIDI,
                .altsetting = 1,
                .ep_ctrl_r = 0x82,
                .ep_ctrl_w = 0x01,
index f6c3bf7..04991b0 100644 (file)
@@ -1831,6 +1831,7 @@ void snd_usb_mixer_rc_memory_change(struct usb_mixer_interface *mixer,
 }
 
 static void snd_dragonfly_quirk_db_scale(struct usb_mixer_interface *mixer,
+                                        struct usb_mixer_elem_info *cval,
                                         struct snd_kcontrol *kctl)
 {
        /* Approximation using 10 ranges based on output measurement on hw v1.2.
@@ -1848,10 +1849,19 @@ static void snd_dragonfly_quirk_db_scale(struct usb_mixer_interface *mixer,
                41, 50, TLV_DB_MINMAX_ITEM(-441, 0),
        );
 
-       usb_audio_info(mixer->chip, "applying DragonFly dB scale quirk\n");
-       kctl->tlv.p = scale;
-       kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
-       kctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK;
+       if (cval->min == 0 && cval->max == 50) {
+               usb_audio_info(mixer->chip, "applying DragonFly dB scale quirk (0-50 variant)\n");
+               kctl->tlv.p = scale;
+               kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
+               kctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK;
+
+       } else if (cval->min == 0 && cval->max <= 1000) {
+               /* Some other clearly broken DragonFly variant.
+                * At least a 0..53 variant (hw v1.0) exists.
+                */
+               usb_audio_info(mixer->chip, "ignoring too narrow dB range on a DragonFly device");
+               kctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK;
+       }
 }
 
 void snd_usb_mixer_fu_apply_quirk(struct usb_mixer_interface *mixer,
@@ -1860,8 +1870,8 @@ void snd_usb_mixer_fu_apply_quirk(struct usb_mixer_interface *mixer,
 {
        switch (mixer->chip->usb_id) {
        case USB_ID(0x21b4, 0x0081): /* AudioQuest DragonFly */
-               if (unitid == 7 && cval->min == 0 && cval->max == 50)
-                       snd_dragonfly_quirk_db_scale(mixer, kctl);
+               if (unitid == 7 && cval->control == UAC_FU_VOLUME)
+                       snd_dragonfly_quirk_db_scale(mixer, cval, kctl);
                break;
        }
 }
index 152292e..2782155 100644 (file)
@@ -1217,6 +1217,12 @@ void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep)
             ep->chip->usb_id == USB_ID(0x0763, 0x2031)) &&
            ep->type == SND_USB_ENDPOINT_TYPE_DATA)
                ep->skip_packets = 16;
+
+       /* Work around devices that report unreasonable feedback data */
+       if ((ep->chip->usb_id == USB_ID(0x0644, 0x8038) ||  /* TEAC UD-H01 */
+            ep->chip->usb_id == USB_ID(0x1852, 0x5034)) && /* T+A Dac8 */
+           ep->syncmaxsize == 4)
+               ep->tenor_fb_quirk = 1;
 }
 
 void snd_usb_set_interface_quirk(struct usb_device *dev)