]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge branch 'topic/usb-mixer-cache' into next/usb-audio
authorTakashi Iwai <tiwai@suse.de>
Sat, 17 Jan 2009 11:01:12 +0000 (12:01 +0100)
committerTakashi Iwai <tiwai@suse.de>
Sat, 17 Jan 2009 11:01:12 +0000 (12:01 +0100)
1  2 
sound/usb/usbmixer.c

diff --combined sound/usb/usbmixer.c
index bc8bd00047ad587272a2c082d4e11d92e0f9b2a3,c07b3f8485e374d01c5586ad2d908a45c396cc0b..330f2fbff2d1fd831db49604d9fc6b891be05256
@@@ -66,7 -66,6 +66,7 @@@ static const struct rc_config 
        { USB_ID(0x041e, 0x3000), 0, 1, 2, 1,  18, 0x0013 }, /* Extigy       */
        { USB_ID(0x041e, 0x3020), 2, 1, 6, 6,  18, 0x0013 }, /* Audigy 2 NX  */
        { USB_ID(0x041e, 0x3040), 2, 2, 6, 6,  2,  0x6e91 }, /* Live! 24-bit */
 +      { USB_ID(0x041e, 0x3048), 2, 2, 6, 6,  2,  0x6e91 }, /* Toshiba SB0500 */
  };
  
  struct usb_mixer_interface {
@@@ -111,6 -110,8 +111,8 @@@ struct mixer_build 
        const struct usbmix_selector_map *selector_map;
  };
  
+ #define MAX_CHANNELS  10      /* max logical channels */
  struct usb_mixer_elem_info {
        struct usb_mixer_interface *mixer;
        struct usb_mixer_elem_info *next_id_elem; /* list of controls with same id */
        int channels;
        int val_type;
        int min, max, res;
+       int cached;
+       int cache_val[MAX_CHANNELS];
        u8 initialized;
  };
  
@@@ -182,8 -185,6 +186,6 @@@ enum 
        USB_PROC_DCR_RELEASE = 6,
  };
  
- #define MAX_CHANNELS  10      /* max logical channels */
  
  /*
   * manual mapping of mixer names
@@@ -377,11 -378,35 +379,35 @@@ static int get_cur_ctl_value(struct usb
  }
  
  /* channel = 0: master, 1 = first channel */
- static inline int get_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, int *value)
+ static inline int get_cur_mix_raw(struct usb_mixer_elem_info *cval,
+                                 int channel, int *value)
  {
        return get_ctl_value(cval, GET_CUR, (cval->control << 8) | channel, value);
  }
  
+ static int get_cur_mix_value(struct usb_mixer_elem_info *cval,
+                            int channel, int index, int *value)
+ {
+       int err;
+       if (cval->cached & (1 << channel)) {
+               *value = cval->cache_val[index];
+               return 0;
+       }
+       err = get_cur_mix_raw(cval, channel, value);
+       if (err < 0) {
+               if (!cval->mixer->ignore_ctl_error)
+                       snd_printd(KERN_ERR "cannot get current value for "
+                                  "control %d ch %d: err = %d\n",
+                                  cval->control, channel, err);
+               return err;
+       }
+       cval->cached |= 1 << channel;
+       cval->cache_val[index] = *value;
+       return 0;
+ }
  /*
   * set a mixer value
   */
@@@ -413,9 -438,17 +439,17 @@@ static int set_cur_ctl_value(struct usb
        return set_ctl_value(cval, SET_CUR, validx, value);
  }
  
- static inline int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, int value)
+ static int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel,
+                            int index, int value)
  {
-       return set_ctl_value(cval, SET_CUR, (cval->control << 8) | channel, value);
+       int err;
+       err = set_ctl_value(cval, SET_CUR, (cval->control << 8) | channel,
+                           value);
+       if (err < 0)
+               return err;
+       cval->cached |= 1 << channel;
+       cval->cache_val[index] = value;
+       return 0;
  }
  
  /*
@@@ -719,7 -752,7 +753,7 @@@ static int get_min_max(struct usb_mixer
                if (cval->min + cval->res < cval->max) {
                        int last_valid_res = cval->res;
                        int saved, test, check;
-                       get_cur_mix_value(cval, minchn, &saved);
+                       get_cur_mix_raw(cval, minchn, &saved);
                        for (;;) {
                                test = saved;
                                if (test < cval->max)
                                else
                                        test -= cval->res;
                                if (test < cval->min || test > cval->max ||
-                                   set_cur_mix_value(cval, minchn, test) ||
-                                   get_cur_mix_value(cval, minchn, &check)) {
+                                   set_cur_mix_value(cval, minchn, 0, test) ||
+                                   get_cur_mix_raw(cval, minchn, &check)) {
                                        cval->res = last_valid_res;
                                        break;
                                }
                                        break;
                                cval->res *= 2;
                        }
-                       set_cur_mix_value(cval, minchn, saved);
+                       set_cur_mix_value(cval, minchn, 0, saved);
                }
  
                cval->initialized = 1;
@@@ -776,35 -809,25 +810,25 @@@ static int mixer_ctl_feature_get(struc
        struct usb_mixer_elem_info *cval = kcontrol->private_data;
        int c, cnt, val, err;
  
+       ucontrol->value.integer.value[0] = cval->min;
        if (cval->cmask) {
                cnt = 0;
                for (c = 0; c < MAX_CHANNELS; c++) {
-                       if (cval->cmask & (1 << c)) {
-                               err = get_cur_mix_value(cval, c + 1, &val);
-                               if (err < 0) {
-                                       if (cval->mixer->ignore_ctl_error) {
-                                               ucontrol->value.integer.value[0] = cval->min;
-                                               return 0;
-                                       }
-                                       snd_printd(KERN_ERR "cannot get current value for control %d ch %d: err = %d\n", cval->control, c + 1, err);
-                                       return err;
-                               }
-                               val = get_relative_value(cval, val);
-                               ucontrol->value.integer.value[cnt] = val;
-                               cnt++;
-                       }
+                       if (!(cval->cmask & (1 << c)))
+                               continue;
+                       err = get_cur_mix_value(cval, c + 1, cnt, &val);
+                       if (err < 0)
+                               return cval->mixer->ignore_ctl_error ? 0 : err;
+                       val = get_relative_value(cval, val);
+                       ucontrol->value.integer.value[cnt] = val;
+                       cnt++;
                }
+               return 0;
        } else {
                /* master channel */
-               err = get_cur_mix_value(cval, 0, &val);
-               if (err < 0) {
-                       if (cval->mixer->ignore_ctl_error) {
-                               ucontrol->value.integer.value[0] = cval->min;
-                               return 0;
-                       }
-                       snd_printd(KERN_ERR "cannot get current value for control %d master ch: err = %d\n", cval->control, err);
-                       return err;
-               }
+               err = get_cur_mix_value(cval, 0, 0, &val);
+               if (err < 0)
+                       return cval->mixer->ignore_ctl_error ? 0 : err;
                val = get_relative_value(cval, val);
                ucontrol->value.integer.value[0] = val;
        }
@@@ -821,34 -844,28 +845,28 @@@ static int mixer_ctl_feature_put(struc
        if (cval->cmask) {
                cnt = 0;
                for (c = 0; c < MAX_CHANNELS; c++) {
-                       if (cval->cmask & (1 << c)) {
-                               err = get_cur_mix_value(cval, c + 1, &oval);
-                               if (err < 0) {
-                                       if (cval->mixer->ignore_ctl_error)
-                                               return 0;
-                                       return err;
-                               }
-                               val = ucontrol->value.integer.value[cnt];
-                               val = get_abs_value(cval, val);
-                               if (oval != val) {
-                                       set_cur_mix_value(cval, c + 1, val);
-                                       changed = 1;
-                               }
-                               get_cur_mix_value(cval, c + 1, &val);
-                               cnt++;
+                       if (!(cval->cmask & (1 << c)))
+                               continue;
+                       err = get_cur_mix_value(cval, c + 1, cnt, &oval);
+                       if (err < 0)
+                               return cval->mixer->ignore_ctl_error ? 0 : err;
+                       val = ucontrol->value.integer.value[cnt];
+                       val = get_abs_value(cval, val);
+                       if (oval != val) {
+                               set_cur_mix_value(cval, c + 1, cnt, val);
+                               changed = 1;
                        }
+                       cnt++;
                }
        } else {
                /* master channel */
-               err = get_cur_mix_value(cval, 0, &oval);
-               if (err < 0 && cval->mixer->ignore_ctl_error)
-                       return 0;
+               err = get_cur_mix_value(cval, 0, 0, &oval);
                if (err < 0)
-                       return err;
+                       return cval->mixer->ignore_ctl_error ? 0 : err;
                val = ucontrol->value.integer.value[0];
                val = get_abs_value(cval, val);
                if (val != oval) {
-                       set_cur_mix_value(cval, 0, val);
+                       set_cur_mix_value(cval, 0, 0, val);
                        changed = 1;
                }
        }
@@@ -1707,8 -1724,7 +1725,8 @@@ static void snd_usb_mixer_memory_change
                break;
        /* live24ext: 4 = line-in jack */
        case 3: /* hp-out jack (may actuate Mute) */
 -              if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040))
 +              if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
 +                  mixer->chip->usb_id == USB_ID(0x041e, 0x3048))
                        snd_usb_mixer_notify_id(mixer, mixer->rc_cfg->mute_mixer_id);
                break;
        default:
@@@ -1958,9 -1974,8 +1976,9 @@@ static int snd_audigy2nx_controls_creat
        int i, err;
  
        for (i = 0; i < ARRAY_SIZE(snd_audigy2nx_controls); ++i) {
 -              if (i > 1 &&  /* Live24ext has 2 LEDs only */
 -                      mixer->chip->usb_id == USB_ID(0x041e, 0x3040))
 +              if (i > 1 && /* Live24ext has 2 LEDs only */
 +                      (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
 +                       mixer->chip->usb_id == USB_ID(0x041e, 0x3048)))
                        break; 
                err = snd_ctl_add(mixer->chip->card,
                                  snd_ctl_new1(&snd_audigy2nx_controls[i], mixer));
@@@ -1997,8 -2012,7 +2015,8 @@@ static void snd_audigy2nx_proc_read(str
        snd_iprintf(buffer, "%s jacks\n\n", mixer->chip->card->shortname);
        if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020))
                jacks = jacks_audigy2nx;
 -      else if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040))
 +      else if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
 +               mixer->chip->usb_id == USB_ID(0x041e, 0x3048))
                jacks = jacks_live24ext;
        else
                return;
@@@ -2048,8 -2062,7 +2066,8 @@@ int snd_usb_create_mixer(struct snd_usb
                goto _error;
  
        if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020) ||
 -          mixer->chip->usb_id == USB_ID(0x041e, 0x3040)) {
 +          mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
 +          mixer->chip->usb_id == USB_ID(0x041e, 0x3048)) {
                struct snd_info_entry *entry;
  
                if ((err = snd_audigy2nx_controls_create(mixer)) < 0)