ALSA: control: fix failure to return new numerical ID in 'replace' event data
[pandora-kernel.git] / sound / core / control.c
index bb96a46..35324a8 100644 (file)
@@ -50,7 +50,7 @@ static int snd_ctl_open(struct inode *inode, struct file *file)
        unsigned long flags;
        struct snd_card *card;
        struct snd_ctl_file *ctl;
-       int err;
+       int i, err;
 
        err = nonseekable_open(inode, file);
        if (err < 0)
@@ -79,8 +79,8 @@ static int snd_ctl_open(struct inode *inode, struct file *file)
        init_waitqueue_head(&ctl->change_sleep);
        spin_lock_init(&ctl->read_lock);
        ctl->card = card;
-       ctl->prefer_pcm_subdevice = -1;
-       ctl->prefer_rawmidi_subdevice = -1;
+       for (i = 0; i < SND_CTL_SUBDEV_ITEMS; i++)
+               ctl->preferred_subdevice[i] = -1;
        ctl->pid = get_pid(task_pid(current));
        file->private_data = ctl;
        write_lock_irqsave(&card->ctl_files_rwlock, flags);
@@ -373,6 +373,7 @@ int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
        card->controls_count += kcontrol->count;
        kcontrol->id.numid = card->last_numid + 1;
        card->last_numid += kcontrol->count;
+       id = kcontrol->id;
        count = kcontrol->count;
        up_write(&card->controls_rwsem);
        for (idx = 0; idx < count; idx++, id.index++, id.numid++)
@@ -439,6 +440,7 @@ add:
        card->controls_count += kcontrol->count;
        kcontrol->id.numid = card->last_numid + 1;
        card->last_numid += kcontrol->count;
+       id = kcontrol->id;
        count = kcontrol->count;
        up_write(&card->controls_rwsem);
        for (idx = 0; idx < count; idx++, id.index++, id.numid++)
@@ -1607,6 +1609,27 @@ static int snd_ctl_fasync(int fd, struct file * file, int on)
        return fasync_helper(fd, file, on, &ctl->fasync);
 }
 
+/* return the preferred subdevice number if already assigned;
+ * otherwise return -1
+ */
+int snd_ctl_get_preferred_subdevice(struct snd_card *card, int type)
+{
+       struct snd_ctl_file *kctl;
+       int subdevice = -1;
+
+       read_lock(&card->ctl_files_rwlock);
+       list_for_each_entry(kctl, &card->ctl_files, list) {
+               if (kctl->pid == task_pid(current)) {
+                       subdevice = kctl->preferred_subdevice[type];
+                       if (subdevice != -1)
+                               break;
+               }
+       }
+       read_unlock(&card->ctl_files_rwlock);
+       return subdevice;
+}
+EXPORT_SYMBOL_GPL(snd_ctl_get_preferred_subdevice);
+
 /*
  * ioctl32 compat
  */
@@ -1639,19 +1662,9 @@ static const struct file_operations snd_ctl_f_ops =
 static int snd_ctl_dev_register(struct snd_device *device)
 {
        struct snd_card *card = device->device_data;
-       int err, cardnum;
-       char name[16];
 
-       if (snd_BUG_ON(!card))
-               return -ENXIO;
-       cardnum = card->number;
-       if (snd_BUG_ON(cardnum < 0 || cardnum >= SNDRV_CARDS))
-               return -ENXIO;
-       sprintf(name, "controlC%i", cardnum);
-       if ((err = snd_register_device(SNDRV_DEVICE_TYPE_CONTROL, card, -1,
-                                      &snd_ctl_f_ops, card, name)) < 0)
-               return err;
-       return 0;
+       return snd_register_device(SNDRV_DEVICE_TYPE_CONTROL, card, -1,
+                                  &snd_ctl_f_ops, card, &card->ctl_dev);
 }
 
 /*
@@ -1661,13 +1674,6 @@ static int snd_ctl_dev_disconnect(struct snd_device *device)
 {
        struct snd_card *card = device->device_data;
        struct snd_ctl_file *ctl;
-       int err, cardnum;
-
-       if (snd_BUG_ON(!card))
-               return -ENXIO;
-       cardnum = card->number;
-       if (snd_BUG_ON(cardnum < 0 || cardnum >= SNDRV_CARDS))
-               return -ENXIO;
 
        read_lock(&card->ctl_files_rwlock);
        list_for_each_entry(ctl, &card->ctl_files, list) {
@@ -1676,10 +1682,7 @@ static int snd_ctl_dev_disconnect(struct snd_device *device)
        }
        read_unlock(&card->ctl_files_rwlock);
 
-       if ((err = snd_unregister_device(SNDRV_DEVICE_TYPE_CONTROL,
-                                        card, -1)) < 0)
-               return err;
-       return 0;
+       return snd_unregister_device(&card->ctl_dev);
 }
 
 /*
@@ -1696,6 +1699,7 @@ static int snd_ctl_dev_free(struct snd_device *device)
                snd_ctl_remove(card, control);
        }
        up_write(&card->controls_rwsem);
+       put_device(&card->ctl_dev);
        return 0;
 }
 
@@ -1710,10 +1714,20 @@ int snd_ctl_create(struct snd_card *card)
                .dev_register = snd_ctl_dev_register,
                .dev_disconnect = snd_ctl_dev_disconnect,
        };
+       int err;
 
        if (snd_BUG_ON(!card))
                return -ENXIO;
-       return snd_device_new(card, SNDRV_DEV_CONTROL, card, &ops);
+       if (snd_BUG_ON(card->number < 0 || card->number >= SNDRV_CARDS))
+               return -ENXIO;
+
+       snd_device_initialize(&card->ctl_dev, card);
+       dev_set_name(&card->ctl_dev, "controlC%d", card->number);
+
+       err = snd_device_new(card, SNDRV_DEV_CONTROL, card, &ops);
+       if (err < 0)
+               put_device(&card->ctl_dev);
+       return err;
 }
 
 /*