linux/sound/usb/mixer_quirks.c
<<
>>
Prefs
   1/*
   2 *   USB Audio Driver for ALSA
   3 *
   4 *   Quirks and vendor-specific extensions for mixer interfaces
   5 *
   6 *   Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>
   7 *
   8 *   Many codes borrowed from audio.c by
   9 *          Alan Cox (alan@lxorguk.ukuu.org.uk)
  10 *          Thomas Sailer (sailer@ife.ee.ethz.ch)
  11 *
  12 *
  13 *   This program is free software; you can redistribute it and/or modify
  14 *   it under the terms of the GNU General Public License as published by
  15 *   the Free Software Foundation; either version 2 of the License, or
  16 *   (at your option) any later version.
  17 *
  18 *   This program is distributed in the hope that it will be useful,
  19 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  20 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21 *   GNU General Public License for more details.
  22 *
  23 *   You should have received a copy of the GNU General Public License
  24 *   along with this program; if not, write to the Free Software
  25 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  26 */
  27
  28#include <linux/init.h>
  29#include <linux/slab.h>
  30#include <linux/usb.h>
  31#include <linux/usb/audio.h>
  32
  33#include <sound/core.h>
  34#include <sound/control.h>
  35#include <sound/hwdep.h>
  36#include <sound/info.h>
  37
  38#include "usbaudio.h"
  39#include "mixer.h"
  40#include "mixer_quirks.h"
  41#include "helper.h"
  42
  43extern struct snd_kcontrol_new *snd_usb_feature_unit_ctl;
  44
  45struct std_mono_table {
  46        unsigned int unitid, control, cmask;
  47        int val_type;
  48        const char *name;
  49        snd_kcontrol_tlv_rw_t *tlv_callback;
  50};
  51
  52/* private_free callback */
  53static void usb_mixer_elem_free(struct snd_kcontrol *kctl)
  54{
  55        kfree(kctl->private_data);
  56        kctl->private_data = NULL;
  57}
  58
  59/* This function allows for the creation of standard UAC controls.
  60 * See the quirks for M-Audio FTUs or Ebox-44.
  61 * If you don't want to set a TLV callback pass NULL.
  62 *
  63 * Since there doesn't seem to be a devices that needs a multichannel
  64 * version, we keep it mono for simplicity.
  65 */
  66static int snd_create_std_mono_ctl(struct usb_mixer_interface *mixer,
  67                                unsigned int unitid,
  68                                unsigned int control,
  69                                unsigned int cmask,
  70                                int val_type,
  71                                const char *name,
  72                                snd_kcontrol_tlv_rw_t *tlv_callback)
  73{
  74        int err;
  75        struct usb_mixer_elem_info *cval;
  76        struct snd_kcontrol *kctl;
  77
  78        cval = kzalloc(sizeof(*cval), GFP_KERNEL);
  79        if (!cval)
  80                return -ENOMEM;
  81
  82        cval->id = unitid;
  83        cval->mixer = mixer;
  84        cval->val_type = val_type;
  85        cval->channels = 1;
  86        cval->control = control;
  87        cval->cmask = cmask;
  88
  89        /* get_min_max() is called only for integer volumes later,
  90         * so provide a short-cut for booleans */
  91        cval->min = 0;
  92        cval->max = 1;
  93        cval->res = 0;
  94        cval->dBmin = 0;
  95        cval->dBmax = 0;
  96
  97        /* Create control */
  98        kctl = snd_ctl_new1(snd_usb_feature_unit_ctl, cval);
  99        if (!kctl) {
 100                kfree(cval);
 101                return -ENOMEM;
 102        }
 103
 104        /* Set name */
 105        snprintf(kctl->id.name, sizeof(kctl->id.name), name);
 106        kctl->private_free = usb_mixer_elem_free;
 107
 108        /* set TLV */
 109        if (tlv_callback) {
 110                kctl->tlv.c = tlv_callback;
 111                kctl->vd[0].access |=
 112                        SNDRV_CTL_ELEM_ACCESS_TLV_READ |
 113                        SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK;
 114        }
 115        /* Add control to mixer */
 116        err = snd_usb_mixer_add_control(mixer, kctl);
 117        if (err < 0)
 118                return err;
 119
 120        return 0;
 121}
 122
 123/*
 124 * Create a set of standard UAC controls from a table
 125 */
 126static int snd_create_std_mono_table(struct usb_mixer_interface *mixer,
 127                                struct std_mono_table *t)
 128{
 129        int err;
 130
 131        while (t->name != NULL) {
 132                err = snd_create_std_mono_ctl(mixer, t->unitid, t->control,
 133                                t->cmask, t->val_type, t->name, t->tlv_callback);
 134                if (err < 0)
 135                        return err;
 136                t++;
 137        }
 138
 139        return 0;
 140}
 141
 142/*
 143 * Sound Blaster remote control configuration
 144 *
 145 * format of remote control data:
 146 * Extigy:       xx 00
 147 * Audigy 2 NX:  06 80 xx 00 00 00
 148 * Live! 24-bit: 06 80 xx yy 22 83
 149 */
 150static const struct rc_config {
 151        u32 usb_id;
 152        u8  offset;
 153        u8  length;
 154        u8  packet_length;
 155        u8  min_packet_length; /* minimum accepted length of the URB result */
 156        u8  mute_mixer_id;
 157        u32 mute_code;
 158} rc_configs[] = {
 159        { USB_ID(0x041e, 0x3000), 0, 1, 2, 1,  18, 0x0013 }, /* Extigy       */
 160        { USB_ID(0x041e, 0x3020), 2, 1, 6, 6,  18, 0x0013 }, /* Audigy 2 NX  */
 161        { USB_ID(0x041e, 0x3040), 2, 2, 6, 6,  2,  0x6e91 }, /* Live! 24-bit */
 162        { USB_ID(0x041e, 0x3042), 0, 1, 1, 1,  1,  0x000d }, /* Usb X-Fi S51 */
 163        { USB_ID(0x041e, 0x30df), 0, 1, 1, 1,  1,  0x000d }, /* Usb X-Fi S51 Pro */
 164        { USB_ID(0x041e, 0x3048), 2, 2, 6, 6,  2,  0x6e91 }, /* Toshiba SB0500 */
 165};
 166
 167static void snd_usb_soundblaster_remote_complete(struct urb *urb)
 168{
 169        struct usb_mixer_interface *mixer = urb->context;
 170        const struct rc_config *rc = mixer->rc_cfg;
 171        u32 code;
 172
 173        if (urb->status < 0 || urb->actual_length < rc->min_packet_length)
 174                return;
 175
 176        code = mixer->rc_buffer[rc->offset];
 177        if (rc->length == 2)
 178                code |= mixer->rc_buffer[rc->offset + 1] << 8;
 179
 180        /* the Mute button actually changes the mixer control */
 181        if (code == rc->mute_code)
 182                snd_usb_mixer_notify_id(mixer, rc->mute_mixer_id);
 183        mixer->rc_code = code;
 184        wmb();
 185        wake_up(&mixer->rc_waitq);
 186}
 187
 188static long snd_usb_sbrc_hwdep_read(struct snd_hwdep *hw, char __user *buf,
 189                                     long count, loff_t *offset)
 190{
 191        struct usb_mixer_interface *mixer = hw->private_data;
 192        int err;
 193        u32 rc_code;
 194
 195        if (count != 1 && count != 4)
 196                return -EINVAL;
 197        err = wait_event_interruptible(mixer->rc_waitq,
 198                                       (rc_code = xchg(&mixer->rc_code, 0)) != 0);
 199        if (err == 0) {
 200                if (count == 1)
 201                        err = put_user(rc_code, buf);
 202                else
 203                        err = put_user(rc_code, (u32 __user *)buf);
 204        }
 205        return err < 0 ? err : count;
 206}
 207
 208static unsigned int snd_usb_sbrc_hwdep_poll(struct snd_hwdep *hw, struct file *file,
 209                                            poll_table *wait)
 210{
 211        struct usb_mixer_interface *mixer = hw->private_data;
 212
 213        poll_wait(file, &mixer->rc_waitq, wait);
 214        return mixer->rc_code ? POLLIN | POLLRDNORM : 0;
 215}
 216
 217static int snd_usb_soundblaster_remote_init(struct usb_mixer_interface *mixer)
 218{
 219        struct snd_hwdep *hwdep;
 220        int err, len, i;
 221
 222        for (i = 0; i < ARRAY_SIZE(rc_configs); ++i)
 223                if (rc_configs[i].usb_id == mixer->chip->usb_id)
 224                        break;
 225        if (i >= ARRAY_SIZE(rc_configs))
 226                return 0;
 227        mixer->rc_cfg = &rc_configs[i];
 228
 229        len = mixer->rc_cfg->packet_length;
 230
 231        init_waitqueue_head(&mixer->rc_waitq);
 232        err = snd_hwdep_new(mixer->chip->card, "SB remote control", 0, &hwdep);
 233        if (err < 0)
 234                return err;
 235        snprintf(hwdep->name, sizeof(hwdep->name),
 236                 "%s remote control", mixer->chip->card->shortname);
 237        hwdep->iface = SNDRV_HWDEP_IFACE_SB_RC;
 238        hwdep->private_data = mixer;
 239        hwdep->ops.read = snd_usb_sbrc_hwdep_read;
 240        hwdep->ops.poll = snd_usb_sbrc_hwdep_poll;
 241        hwdep->exclusive = 1;
 242
 243        mixer->rc_urb = usb_alloc_urb(0, GFP_KERNEL);
 244        if (!mixer->rc_urb)
 245                return -ENOMEM;
 246        mixer->rc_setup_packet = kmalloc(sizeof(*mixer->rc_setup_packet), GFP_KERNEL);
 247        if (!mixer->rc_setup_packet) {
 248                usb_free_urb(mixer->rc_urb);
 249                mixer->rc_urb = NULL;
 250                return -ENOMEM;
 251        }
 252        mixer->rc_setup_packet->bRequestType =
 253                USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
 254        mixer->rc_setup_packet->bRequest = UAC_GET_MEM;
 255        mixer->rc_setup_packet->wValue = cpu_to_le16(0);
 256        mixer->rc_setup_packet->wIndex = cpu_to_le16(0);
 257        mixer->rc_setup_packet->wLength = cpu_to_le16(len);
 258        usb_fill_control_urb(mixer->rc_urb, mixer->chip->dev,
 259                             usb_rcvctrlpipe(mixer->chip->dev, 0),
 260                             (u8*)mixer->rc_setup_packet, mixer->rc_buffer, len,
 261                             snd_usb_soundblaster_remote_complete, mixer);
 262        return 0;
 263}
 264
 265#define snd_audigy2nx_led_info          snd_ctl_boolean_mono_info
 266
 267static int snd_audigy2nx_led_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 268{
 269        struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
 270        int index = kcontrol->private_value;
 271
 272        ucontrol->value.integer.value[0] = mixer->audigy2nx_leds[index];
 273        return 0;
 274}
 275
 276static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 277{
 278        struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
 279        int index = kcontrol->private_value;
 280        int value = ucontrol->value.integer.value[0];
 281        int err, changed;
 282
 283        if (value > 1)
 284                return -EINVAL;
 285        changed = value != mixer->audigy2nx_leds[index];
 286        if (mixer->chip->usb_id == USB_ID(0x041e, 0x3042))
 287                err = snd_usb_ctl_msg(mixer->chip->dev,
 288                              usb_sndctrlpipe(mixer->chip->dev, 0), 0x24,
 289                              USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
 290                              !value, 0, NULL, 0);
 291        /* USB X-Fi S51 Pro */
 292        if (mixer->chip->usb_id == USB_ID(0x041e, 0x30df))
 293                err = snd_usb_ctl_msg(mixer->chip->dev,
 294                              usb_sndctrlpipe(mixer->chip->dev, 0), 0x24,
 295                              USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
 296                              !value, 0, NULL, 0);
 297        else
 298                err = snd_usb_ctl_msg(mixer->chip->dev,
 299                              usb_sndctrlpipe(mixer->chip->dev, 0), 0x24,
 300                              USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
 301                              value, index + 2, NULL, 0);
 302        if (err < 0)
 303                return err;
 304        mixer->audigy2nx_leds[index] = value;
 305        return changed;
 306}
 307
 308static struct snd_kcontrol_new snd_audigy2nx_controls[] = {
 309        {
 310                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 311                .name = "CMSS LED Switch",
 312                .info = snd_audigy2nx_led_info,
 313                .get = snd_audigy2nx_led_get,
 314                .put = snd_audigy2nx_led_put,
 315                .private_value = 0,
 316        },
 317        {
 318                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 319                .name = "Power LED Switch",
 320                .info = snd_audigy2nx_led_info,
 321                .get = snd_audigy2nx_led_get,
 322                .put = snd_audigy2nx_led_put,
 323                .private_value = 1,
 324        },
 325        {
 326                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 327                .name = "Dolby Digital LED Switch",
 328                .info = snd_audigy2nx_led_info,
 329                .get = snd_audigy2nx_led_get,
 330                .put = snd_audigy2nx_led_put,
 331                .private_value = 2,
 332        },
 333};
 334
 335static int snd_audigy2nx_controls_create(struct usb_mixer_interface *mixer)
 336{
 337        int i, err;
 338
 339        for (i = 0; i < ARRAY_SIZE(snd_audigy2nx_controls); ++i) {
 340                /* USB X-Fi S51 doesn't have a CMSS LED */
 341                if ((mixer->chip->usb_id == USB_ID(0x041e, 0x3042)) && i == 0)
 342                        continue;
 343                /* USB X-Fi S51 Pro doesn't have one either */
 344                if ((mixer->chip->usb_id == USB_ID(0x041e, 0x30df)) && i == 0)
 345                        continue;
 346                if (i > 1 && /* Live24ext has 2 LEDs only */
 347                        (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
 348                         mixer->chip->usb_id == USB_ID(0x041e, 0x3042) ||
 349                         mixer->chip->usb_id == USB_ID(0x041e, 0x30df) ||
 350                         mixer->chip->usb_id == USB_ID(0x041e, 0x3048)))
 351                        break; 
 352                err = snd_ctl_add(mixer->chip->card,
 353                                  snd_ctl_new1(&snd_audigy2nx_controls[i], mixer));
 354                if (err < 0)
 355                        return err;
 356        }
 357        mixer->audigy2nx_leds[1] = 1; /* Power LED is on by default */
 358        return 0;
 359}
 360
 361static void snd_audigy2nx_proc_read(struct snd_info_entry *entry,
 362                                    struct snd_info_buffer *buffer)
 363{
 364        static const struct sb_jack {
 365                int unitid;
 366                const char *name;
 367        }  jacks_audigy2nx[] = {
 368                {4,  "dig in "},
 369                {7,  "line in"},
 370                {19, "spk out"},
 371                {20, "hph out"},
 372                {-1, NULL}
 373        }, jacks_live24ext[] = {
 374                {4,  "line in"}, /* &1=Line, &2=Mic*/
 375                {3,  "hph out"}, /* headphones */
 376                {0,  "RC     "}, /* last command, 6 bytes see rc_config above */
 377                {-1, NULL}
 378        };
 379        const struct sb_jack *jacks;
 380        struct usb_mixer_interface *mixer = entry->private_data;
 381        int i, err;
 382        u8 buf[3];
 383
 384        snd_iprintf(buffer, "%s jacks\n\n", mixer->chip->card->shortname);
 385        if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020))
 386                jacks = jacks_audigy2nx;
 387        else if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
 388                 mixer->chip->usb_id == USB_ID(0x041e, 0x3048))
 389                jacks = jacks_live24ext;
 390        else
 391                return;
 392
 393        for (i = 0; jacks[i].name; ++i) {
 394                snd_iprintf(buffer, "%s: ", jacks[i].name);
 395                err = snd_usb_ctl_msg(mixer->chip->dev,
 396                                      usb_rcvctrlpipe(mixer->chip->dev, 0),
 397                                      UAC_GET_MEM, USB_DIR_IN | USB_TYPE_CLASS |
 398                                      USB_RECIP_INTERFACE, 0,
 399                                      jacks[i].unitid << 8, buf, 3);
 400                if (err == 3 && (buf[0] == 3 || buf[0] == 6))
 401                        snd_iprintf(buffer, "%02x %02x\n", buf[1], buf[2]);
 402                else
 403                        snd_iprintf(buffer, "?\n");
 404        }
 405}
 406
 407static int snd_xonar_u1_switch_get(struct snd_kcontrol *kcontrol,
 408                                   struct snd_ctl_elem_value *ucontrol)
 409{
 410        struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
 411
 412        ucontrol->value.integer.value[0] = !!(mixer->xonar_u1_status & 0x02);
 413        return 0;
 414}
 415
 416static int snd_xonar_u1_switch_put(struct snd_kcontrol *kcontrol,
 417                                   struct snd_ctl_elem_value *ucontrol)
 418{
 419        struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
 420        u8 old_status, new_status;
 421        int err, changed;
 422
 423        old_status = mixer->xonar_u1_status;
 424        if (ucontrol->value.integer.value[0])
 425                new_status = old_status | 0x02;
 426        else
 427                new_status = old_status & ~0x02;
 428        changed = new_status != old_status;
 429        err = snd_usb_ctl_msg(mixer->chip->dev,
 430                              usb_sndctrlpipe(mixer->chip->dev, 0), 0x08,
 431                              USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
 432                              50, 0, &new_status, 1);
 433        if (err < 0)
 434                return err;
 435        mixer->xonar_u1_status = new_status;
 436        return changed;
 437}
 438
 439static struct snd_kcontrol_new snd_xonar_u1_output_switch = {
 440        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 441        .name = "Digital Playback Switch",
 442        .info = snd_ctl_boolean_mono_info,
 443        .get = snd_xonar_u1_switch_get,
 444        .put = snd_xonar_u1_switch_put,
 445};
 446
 447static int snd_xonar_u1_controls_create(struct usb_mixer_interface *mixer)
 448{
 449        int err;
 450
 451        err = snd_ctl_add(mixer->chip->card,
 452                          snd_ctl_new1(&snd_xonar_u1_output_switch, mixer));
 453        if (err < 0)
 454                return err;
 455        mixer->xonar_u1_status = 0x05;
 456        return 0;
 457}
 458
 459/* Native Instruments device quirks */
 460
 461#define _MAKE_NI_CONTROL(bRequest,wIndex) ((bRequest) << 16 | (wIndex))
 462
 463static int snd_nativeinstruments_control_get(struct snd_kcontrol *kcontrol,
 464                                             struct snd_ctl_elem_value *ucontrol)
 465{
 466        struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
 467        struct usb_device *dev = mixer->chip->dev;
 468        u8 bRequest = (kcontrol->private_value >> 16) & 0xff;
 469        u16 wIndex = kcontrol->private_value & 0xffff;
 470        u8 tmp;
 471
 472        int ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest,
 473                                  USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
 474                                  0, cpu_to_le16(wIndex),
 475                                  &tmp, sizeof(tmp), 1000);
 476
 477        if (ret < 0) {
 478                snd_printk(KERN_ERR
 479                           "unable to issue vendor read request (ret = %d)", ret);
 480                return ret;
 481        }
 482
 483        ucontrol->value.integer.value[0] = tmp;
 484
 485        return 0;
 486}
 487
 488static int snd_nativeinstruments_control_put(struct snd_kcontrol *kcontrol,
 489                                             struct snd_ctl_elem_value *ucontrol)
 490{
 491        struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
 492        struct usb_device *dev = mixer->chip->dev;
 493        u8 bRequest = (kcontrol->private_value >> 16) & 0xff;
 494        u16 wIndex = kcontrol->private_value & 0xffff;
 495        u16 wValue = ucontrol->value.integer.value[0];
 496
 497        int ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest,
 498                                  USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
 499                                  cpu_to_le16(wValue), cpu_to_le16(wIndex),
 500                                  NULL, 0, 1000);
 501
 502        if (ret < 0) {
 503                snd_printk(KERN_ERR
 504                           "unable to issue vendor write request (ret = %d)", ret);
 505                return ret;
 506        }
 507
 508        return 0;
 509}
 510
 511static struct snd_kcontrol_new snd_nativeinstruments_ta6_mixers[] = {
 512        {
 513                .name = "Direct Thru Channel A",
 514                .private_value = _MAKE_NI_CONTROL(0x01, 0x03),
 515        },
 516        {
 517                .name = "Direct Thru Channel B",
 518                .private_value = _MAKE_NI_CONTROL(0x01, 0x05),
 519        },
 520        {
 521                .name = "Phono Input Channel A",
 522                .private_value = _MAKE_NI_CONTROL(0x02, 0x03),
 523        },
 524        {
 525                .name = "Phono Input Channel B",
 526                .private_value = _MAKE_NI_CONTROL(0x02, 0x05),
 527        },
 528};
 529
 530static struct snd_kcontrol_new snd_nativeinstruments_ta10_mixers[] = {
 531        {
 532                .name = "Direct Thru Channel A",
 533                .private_value = _MAKE_NI_CONTROL(0x01, 0x03),
 534        },
 535        {
 536                .name = "Direct Thru Channel B",
 537                .private_value = _MAKE_NI_CONTROL(0x01, 0x05),
 538        },
 539        {
 540                .name = "Direct Thru Channel C",
 541                .private_value = _MAKE_NI_CONTROL(0x01, 0x07),
 542        },
 543        {
 544                .name = "Direct Thru Channel D",
 545                .private_value = _MAKE_NI_CONTROL(0x01, 0x09),
 546        },
 547        {
 548                .name = "Phono Input Channel A",
 549                .private_value = _MAKE_NI_CONTROL(0x02, 0x03),
 550        },
 551        {
 552                .name = "Phono Input Channel B",
 553                .private_value = _MAKE_NI_CONTROL(0x02, 0x05),
 554        },
 555        {
 556                .name = "Phono Input Channel C",
 557                .private_value = _MAKE_NI_CONTROL(0x02, 0x07),
 558        },
 559        {
 560                .name = "Phono Input Channel D",
 561                .private_value = _MAKE_NI_CONTROL(0x02, 0x09),
 562        },
 563};
 564
 565static int snd_nativeinstruments_create_mixer(struct usb_mixer_interface *mixer,
 566                                              const struct snd_kcontrol_new *kc,
 567                                              unsigned int count)
 568{
 569        int i, err = 0;
 570        struct snd_kcontrol_new template = {
 571                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 572                .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
 573                .get = snd_nativeinstruments_control_get,
 574                .put = snd_nativeinstruments_control_put,
 575                .info = snd_ctl_boolean_mono_info,
 576        };
 577
 578        for (i = 0; i < count; i++) {
 579                struct snd_kcontrol *c;
 580
 581                template.name = kc[i].name;
 582                template.private_value = kc[i].private_value;
 583
 584                c = snd_ctl_new1(&template, mixer);
 585                err = snd_ctl_add(mixer->chip->card, c);
 586
 587                if (err < 0)
 588                        break;
 589        }
 590
 591        return err;
 592}
 593
 594/* M-Audio FastTrack Ultra quirks */
 595/* FTU Effect switch */
 596struct snd_ftu_eff_switch_priv_val {
 597        struct usb_mixer_interface *mixer;
 598        int cached_value;
 599        int is_cached;
 600};
 601
 602static int snd_ftu_eff_switch_info(struct snd_kcontrol *kcontrol,
 603                                        struct snd_ctl_elem_info *uinfo)
 604{
 605        static const char *texts[8] = {"Room 1",
 606                                       "Room 2",
 607                                       "Room 3",
 608                                       "Hall 1",
 609                                       "Hall 2",
 610                                       "Plate",
 611                                       "Delay",
 612                                       "Echo"
 613        };
 614
 615        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 616        uinfo->count = 1;
 617        uinfo->value.enumerated.items = 8;
 618        if (uinfo->value.enumerated.item > 7)
 619                uinfo->value.enumerated.item = 7;
 620        strcpy(uinfo->value.enumerated.name,
 621                texts[uinfo->value.enumerated.item]);
 622
 623        return 0;
 624}
 625
 626static int snd_ftu_eff_switch_get(struct snd_kcontrol *kctl,
 627                                        struct snd_ctl_elem_value *ucontrol)
 628{
 629        struct snd_usb_audio *chip;
 630        struct usb_mixer_interface *mixer;
 631        struct snd_ftu_eff_switch_priv_val *pval;
 632        int err;
 633        unsigned char value[2];
 634
 635        const int id = 6;
 636        const int validx = 1;
 637        const int val_len = 2;
 638
 639        value[0] = 0x00;
 640        value[1] = 0x00;
 641
 642        pval = (struct snd_ftu_eff_switch_priv_val *)
 643                kctl->private_value;
 644
 645        if (pval->is_cached) {
 646                ucontrol->value.enumerated.item[0] = pval->cached_value;
 647                return 0;
 648        }
 649
 650        mixer = (struct usb_mixer_interface *) pval->mixer;
 651        if (snd_BUG_ON(!mixer))
 652                return -EINVAL;
 653
 654        chip = (struct snd_usb_audio *) mixer->chip;
 655        if (snd_BUG_ON(!chip))
 656                return -EINVAL;
 657
 658
 659        err = snd_usb_ctl_msg(chip->dev,
 660                        usb_rcvctrlpipe(chip->dev, 0), UAC_GET_CUR,
 661                        USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
 662                        validx << 8, snd_usb_ctrl_intf(chip) | (id << 8),
 663                        value, val_len);
 664        if (err < 0)
 665                return err;
 666
 667        ucontrol->value.enumerated.item[0] = value[0];
 668        pval->cached_value = value[0];
 669        pval->is_cached = 1;
 670
 671        return 0;
 672}
 673
 674static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl,
 675                                        struct snd_ctl_elem_value *ucontrol)
 676{
 677        struct snd_usb_audio *chip;
 678        struct snd_ftu_eff_switch_priv_val *pval;
 679
 680        struct usb_mixer_interface *mixer;
 681        int changed, cur_val, err, new_val;
 682        unsigned char value[2];
 683
 684
 685        const int id = 6;
 686        const int validx = 1;
 687        const int val_len = 2;
 688
 689        changed = 0;
 690
 691        pval = (struct snd_ftu_eff_switch_priv_val *)
 692                kctl->private_value;
 693        cur_val = pval->cached_value;
 694        new_val = ucontrol->value.enumerated.item[0];
 695
 696        mixer = (struct usb_mixer_interface *) pval->mixer;
 697        if (snd_BUG_ON(!mixer))
 698                return -EINVAL;
 699
 700        chip = (struct snd_usb_audio *) mixer->chip;
 701        if (snd_BUG_ON(!chip))
 702                return -EINVAL;
 703
 704        if (!pval->is_cached) {
 705                /* Read current value */
 706                err = snd_usb_ctl_msg(chip->dev,
 707                                usb_rcvctrlpipe(chip->dev, 0), UAC_GET_CUR,
 708                                USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
 709                                validx << 8, snd_usb_ctrl_intf(chip) | (id << 8),
 710                                value, val_len);
 711                if (err < 0)
 712                        return err;
 713
 714                cur_val = value[0];
 715                pval->cached_value = cur_val;
 716                pval->is_cached = 1;
 717        }
 718        /* update value if needed */
 719        if (cur_val != new_val) {
 720                value[0] = new_val;
 721                value[1] = 0;
 722                err = snd_usb_ctl_msg(chip->dev,
 723                                usb_sndctrlpipe(chip->dev, 0), UAC_SET_CUR,
 724                                USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
 725                                validx << 8, snd_usb_ctrl_intf(chip) | (id << 8),
 726                                value, val_len);
 727                if (err < 0)
 728                        return err;
 729
 730                pval->cached_value = new_val;
 731                pval->is_cached = 1;
 732                changed = 1;
 733        }
 734
 735        return changed;
 736}
 737
 738static int snd_ftu_create_effect_switch(struct usb_mixer_interface *mixer)
 739{
 740        static struct snd_kcontrol_new template = {
 741                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 742                .name = "Effect Program Switch",
 743                .index = 0,
 744                .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
 745                .info = snd_ftu_eff_switch_info,
 746                .get = snd_ftu_eff_switch_get,
 747                .put = snd_ftu_eff_switch_put
 748        };
 749
 750        int err;
 751        struct snd_kcontrol *kctl;
 752        struct snd_ftu_eff_switch_priv_val *pval;
 753
 754        pval = kzalloc(sizeof(*pval), GFP_KERNEL);
 755        if (!pval)
 756                return -ENOMEM;
 757
 758        pval->cached_value = 0;
 759        pval->is_cached = 0;
 760        pval->mixer = mixer;
 761
 762        template.private_value = (unsigned long) pval;
 763        kctl = snd_ctl_new1(&template, mixer->chip);
 764        if (!kctl) {
 765                kfree(pval);
 766                return -ENOMEM;
 767        }
 768
 769        err = snd_ctl_add(mixer->chip->card, kctl);
 770        if (err < 0)
 771                return err;
 772
 773        return 0;
 774}
 775
 776/* Create volume controls for FTU devices*/
 777static int snd_ftu_create_volume_ctls(struct usb_mixer_interface *mixer)
 778{
 779        char name[64];
 780        unsigned int control, cmask;
 781        int in, out, err;
 782
 783        const unsigned int id = 5;
 784        const int val_type = USB_MIXER_S16;
 785
 786        for (out = 0; out < 8; out++) {
 787                control = out + 1;
 788                for (in = 0; in < 8; in++) {
 789                        cmask = 1 << in;
 790                        snprintf(name, sizeof(name),
 791                                "AIn%d - Out%d Capture Volume",
 792                                in  + 1, out + 1);
 793                        err = snd_create_std_mono_ctl(mixer, id, control,
 794                                                        cmask, val_type, name,
 795                                                        &snd_usb_mixer_vol_tlv);
 796                        if (err < 0)
 797                                return err;
 798                }
 799                for (in = 8; in < 16; in++) {
 800                        cmask = 1 << in;
 801                        snprintf(name, sizeof(name),
 802                                "DIn%d - Out%d Playback Volume",
 803                                in - 7, out + 1);
 804                        err = snd_create_std_mono_ctl(mixer, id, control,
 805                                                        cmask, val_type, name,
 806                                                        &snd_usb_mixer_vol_tlv);
 807                        if (err < 0)
 808                                return err;
 809                }
 810        }
 811
 812        return 0;
 813}
 814
 815/* This control needs a volume quirk, see mixer.c */
 816static int snd_ftu_create_effect_volume_ctl(struct usb_mixer_interface *mixer)
 817{
 818        static const char name[] = "Effect Volume";
 819        const unsigned int id = 6;
 820        const int val_type = USB_MIXER_U8;
 821        const unsigned int control = 2;
 822        const unsigned int cmask = 0;
 823
 824        return snd_create_std_mono_ctl(mixer, id, control, cmask, val_type,
 825                                        name, snd_usb_mixer_vol_tlv);
 826}
 827
 828/* This control needs a volume quirk, see mixer.c */
 829static int snd_ftu_create_effect_duration_ctl(struct usb_mixer_interface *mixer)
 830{
 831        static const char name[] = "Effect Duration";
 832        const unsigned int id = 6;
 833        const int val_type = USB_MIXER_S16;
 834        const unsigned int control = 3;
 835        const unsigned int cmask = 0;
 836
 837        return snd_create_std_mono_ctl(mixer, id, control, cmask, val_type,
 838                                        name, snd_usb_mixer_vol_tlv);
 839}
 840
 841/* This control needs a volume quirk, see mixer.c */
 842static int snd_ftu_create_effect_feedback_ctl(struct usb_mixer_interface *mixer)
 843{
 844        static const char name[] = "Effect Feedback Volume";
 845        const unsigned int id = 6;
 846        const int val_type = USB_MIXER_U8;
 847        const unsigned int control = 4;
 848        const unsigned int cmask = 0;
 849
 850        return snd_create_std_mono_ctl(mixer, id, control, cmask, val_type,
 851                                        name, NULL);
 852}
 853
 854static int snd_ftu_create_effect_return_ctls(struct usb_mixer_interface *mixer)
 855{
 856        unsigned int cmask;
 857        int err, ch;
 858        char name[48];
 859
 860        const unsigned int id = 7;
 861        const int val_type = USB_MIXER_S16;
 862        const unsigned int control = 7;
 863
 864        for (ch = 0; ch < 4; ++ch) {
 865                cmask = 1 << ch;
 866                snprintf(name, sizeof(name),
 867                        "Effect Return %d Volume", ch + 1);
 868                err = snd_create_std_mono_ctl(mixer, id, control,
 869                                                cmask, val_type, name,
 870                                                snd_usb_mixer_vol_tlv);
 871                if (err < 0)
 872                        return err;
 873        }
 874
 875        return 0;
 876}
 877
 878static int snd_ftu_create_effect_send_ctls(struct usb_mixer_interface *mixer)
 879{
 880        unsigned int  cmask;
 881        int err, ch;
 882        char name[48];
 883
 884        const unsigned int id = 5;
 885        const int val_type = USB_MIXER_S16;
 886        const unsigned int control = 9;
 887
 888        for (ch = 0; ch < 8; ++ch) {
 889                cmask = 1 << ch;
 890                snprintf(name, sizeof(name),
 891                        "Effect Send AIn%d Volume", ch + 1);
 892                err = snd_create_std_mono_ctl(mixer, id, control, cmask,
 893                                                val_type, name,
 894                                                snd_usb_mixer_vol_tlv);
 895                if (err < 0)
 896                        return err;
 897        }
 898        for (ch = 8; ch < 16; ++ch) {
 899                cmask = 1 << ch;
 900                snprintf(name, sizeof(name),
 901                        "Effect Send DIn%d Volume", ch - 7);
 902                err = snd_create_std_mono_ctl(mixer, id, control, cmask,
 903                                                val_type, name,
 904                                                snd_usb_mixer_vol_tlv);
 905                if (err < 0)
 906                        return err;
 907        }
 908        return 0;
 909}
 910
 911static int snd_ftu_create_mixer(struct usb_mixer_interface *mixer)
 912{
 913        int err;
 914
 915        err = snd_ftu_create_volume_ctls(mixer);
 916        if (err < 0)
 917                return err;
 918
 919        err = snd_ftu_create_effect_switch(mixer);
 920        if (err < 0)
 921                return err;
 922        err = snd_ftu_create_effect_volume_ctl(mixer);
 923        if (err < 0)
 924                return err;
 925
 926        err = snd_ftu_create_effect_duration_ctl(mixer);
 927        if (err < 0)
 928                return err;
 929
 930        err = snd_ftu_create_effect_feedback_ctl(mixer);
 931        if (err < 0)
 932                return err;
 933
 934        err = snd_ftu_create_effect_return_ctls(mixer);
 935        if (err < 0)
 936                return err;
 937
 938        err = snd_ftu_create_effect_send_ctls(mixer);
 939        if (err < 0)
 940                return err;
 941
 942        return 0;
 943}
 944
 945void snd_emuusb_set_samplerate(struct snd_usb_audio *chip,
 946                               unsigned char samplerate_id)
 947{
 948        struct usb_mixer_interface *mixer;
 949        struct usb_mixer_elem_info *cval;
 950        int unitid = 12; /* SamleRate ExtensionUnit ID */
 951
 952        list_for_each_entry(mixer, &chip->mixer_list, list) {
 953                cval = mixer->id_elems[unitid];
 954                if (cval) {
 955                        snd_usb_mixer_set_ctl_value(cval, UAC_SET_CUR,
 956                                                    cval->control << 8,
 957                                                    samplerate_id);
 958                        snd_usb_mixer_notify_id(mixer, unitid);
 959                }
 960                break;
 961        }
 962}
 963
 964/*
 965 * The mixer units for Ebox-44 are corrupt, and even where they
 966 * are valid they presents mono controls as L and R channels of
 967 * stereo. So we provide a good mixer here.
 968 */
 969struct std_mono_table ebox44_table[] = {
 970        {
 971                .unitid = 4,
 972                .control = 1,
 973                .cmask = 0x0,
 974                .val_type = USB_MIXER_INV_BOOLEAN,
 975                .name = "Headphone Playback Switch"
 976        },
 977        {
 978                .unitid = 4,
 979                .control = 2,
 980                .cmask = 0x1,
 981                .val_type = USB_MIXER_S16,
 982                .name = "Headphone A Mix Playback Volume"
 983        },
 984        {
 985                .unitid = 4,
 986                .control = 2,
 987                .cmask = 0x2,
 988                .val_type = USB_MIXER_S16,
 989                .name = "Headphone B Mix Playback Volume"
 990        },
 991
 992        {
 993                .unitid = 7,
 994                .control = 1,
 995                .cmask = 0x0,
 996                .val_type = USB_MIXER_INV_BOOLEAN,
 997                .name = "Output Playback Switch"
 998        },
 999        {
1000                .unitid = 7,
1001                .control = 2,
1002                .cmask = 0x1,
1003                .val_type = USB_MIXER_S16,
1004                .name = "Output A Playback Volume"
1005        },
1006        {
1007                .unitid = 7,
1008                .control = 2,
1009                .cmask = 0x2,
1010                .val_type = USB_MIXER_S16,
1011                .name = "Output B Playback Volume"
1012        },
1013
1014        {
1015                .unitid = 10,
1016                .control = 1,
1017                .cmask = 0x0,
1018                .val_type = USB_MIXER_INV_BOOLEAN,
1019                .name = "Input Capture Switch"
1020        },
1021        {
1022                .unitid = 10,
1023                .control = 2,
1024                .cmask = 0x1,
1025                .val_type = USB_MIXER_S16,
1026                .name = "Input A Capture Volume"
1027        },
1028        {
1029                .unitid = 10,
1030                .control = 2,
1031                .cmask = 0x2,
1032                .val_type = USB_MIXER_S16,
1033                .name = "Input B Capture Volume"
1034        },
1035
1036        {}
1037};
1038
1039int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
1040{
1041        int err = 0;
1042        struct snd_info_entry *entry;
1043
1044        if ((err = snd_usb_soundblaster_remote_init(mixer)) < 0)
1045                return err;
1046
1047        switch (mixer->chip->usb_id) {
1048        case USB_ID(0x041e, 0x3020):
1049        case USB_ID(0x041e, 0x3040):
1050        case USB_ID(0x041e, 0x3042):
1051        case USB_ID(0x041e, 0x30df):
1052        case USB_ID(0x041e, 0x3048):
1053                err = snd_audigy2nx_controls_create(mixer);
1054                if (err < 0)
1055                        break;
1056                if (!snd_card_proc_new(mixer->chip->card, "audigy2nx", &entry))
1057                        snd_info_set_text_ops(entry, mixer,
1058                                              snd_audigy2nx_proc_read);
1059                break;
1060
1061        case USB_ID(0x0763, 0x2080): /* M-Audio Fast Track Ultra */
1062        case USB_ID(0x0763, 0x2081): /* M-Audio Fast Track Ultra 8R */
1063                err = snd_ftu_create_mixer(mixer);
1064                break;
1065
1066        case USB_ID(0x0b05, 0x1739):
1067        case USB_ID(0x0b05, 0x1743):
1068                err = snd_xonar_u1_controls_create(mixer);
1069                break;
1070
1071        case USB_ID(0x17cc, 0x1011): /* Traktor Audio 6 */
1072                err = snd_nativeinstruments_create_mixer(mixer,
1073                                snd_nativeinstruments_ta6_mixers,
1074                                ARRAY_SIZE(snd_nativeinstruments_ta6_mixers));
1075                break;
1076
1077        case USB_ID(0x17cc, 0x1021): /* Traktor Audio 10 */
1078                err = snd_nativeinstruments_create_mixer(mixer,
1079                                snd_nativeinstruments_ta10_mixers,
1080                                ARRAY_SIZE(snd_nativeinstruments_ta10_mixers));
1081                break;
1082
1083        case USB_ID(0x200c, 0x1018): /* Electrix Ebox-44 */
1084                /* detection is disabled in mixer_maps.c */
1085                err = snd_create_std_mono_table(mixer, ebox44_table);
1086                break;
1087        }
1088
1089        return err;
1090}
1091
1092void snd_usb_mixer_rc_memory_change(struct usb_mixer_interface *mixer,
1093                                    int unitid)
1094{
1095        if (!mixer->rc_cfg)
1096                return;
1097        /* unit ids specific to Extigy/Audigy 2 NX: */
1098        switch (unitid) {
1099        case 0: /* remote control */
1100                mixer->rc_urb->dev = mixer->chip->dev;
1101                usb_submit_urb(mixer->rc_urb, GFP_ATOMIC);
1102                break;
1103        case 4: /* digital in jack */
1104        case 7: /* line in jacks */
1105        case 19: /* speaker out jacks */
1106        case 20: /* headphones out jack */
1107                break;
1108        /* live24ext: 4 = line-in jack */
1109        case 3: /* hp-out jack (may actuate Mute) */
1110                if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
1111                    mixer->chip->usb_id == USB_ID(0x041e, 0x3048))
1112                        snd_usb_mixer_notify_id(mixer, mixer->rc_cfg->mute_mixer_id);
1113                break;
1114        default:
1115                snd_printd(KERN_DEBUG "memory change in unknown unit %d\n", unitid);
1116                break;
1117        }
1118}
1119
1120
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.