Merge branches 'clk-renesas', 'clk-cleanup' and 'clk-determine-divider' into clk...
[linux-2.6-microblaze.git] / sound / core / init.c
index ef41f5b..1490568 100644 (file)
@@ -220,6 +220,8 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
        mutex_init(&card->memory_mutex);
 #ifdef CONFIG_PM
        init_waitqueue_head(&card->power_sleep);
+       init_waitqueue_head(&card->power_ref_sleep);
+       atomic_set(&card->power_ref, 0);
 #endif
        init_waitqueue_head(&card->remove_sleep);
        card->sync_irq = -1;
@@ -442,6 +444,7 @@ int snd_card_disconnect(struct snd_card *card)
 
 #ifdef CONFIG_PM
        wake_up(&card->power_sleep);
+       snd_power_sync_ref(card);
 #endif
        return 0;       
 }
@@ -662,17 +665,15 @@ void snd_card_set_id(struct snd_card *card, const char *nid)
 }
 EXPORT_SYMBOL(snd_card_set_id);
 
-static ssize_t
-card_id_show_attr(struct device *dev,
-                 struct device_attribute *attr, char *buf)
+static ssize_t id_show(struct device *dev,
+                      struct device_attribute *attr, char *buf)
 {
        struct snd_card *card = container_of(dev, struct snd_card, card_dev);
        return scnprintf(buf, PAGE_SIZE, "%s\n", card->id);
 }
 
-static ssize_t
-card_id_store_attr(struct device *dev, struct device_attribute *attr,
-                  const char *buf, size_t count)
+static ssize_t id_store(struct device *dev, struct device_attribute *attr,
+                       const char *buf, size_t count)
 {
        struct snd_card *card = container_of(dev, struct snd_card, card_dev);
        char buf1[sizeof(card->id)];
@@ -700,17 +701,16 @@ card_id_store_attr(struct device *dev, struct device_attribute *attr,
        return count;
 }
 
-static DEVICE_ATTR(id, 0644, card_id_show_attr, card_id_store_attr);
+static DEVICE_ATTR_RW(id);
 
-static ssize_t
-card_number_show_attr(struct device *dev,
-                    struct device_attribute *attr, char *buf)
+static ssize_t number_show(struct device *dev,
+                          struct device_attribute *attr, char *buf)
 {
        struct snd_card *card = container_of(dev, struct snd_card, card_dev);
        return scnprintf(buf, PAGE_SIZE, "%i\n", card->number);
 }
 
-static DEVICE_ATTR(number, 0444, card_number_show_attr, NULL);
+static DEVICE_ATTR_RO(number);
 
 static struct attribute *card_dev_attrs[] = {
        &dev_attr_id.attr,
@@ -770,7 +770,8 @@ int snd_card_register(struct snd_card *card)
                card->registered = true;
        }
 
-       if ((err = snd_device_register_all(card)) < 0)
+       err = snd_device_register_all(card);
+       if (err < 0)
                return err;
        mutex_lock(&snd_card_mutex);
        if (snd_cards[card->number]) {
@@ -813,7 +814,8 @@ static void snd_card_info_read(struct snd_info_entry *entry,
 
        for (idx = count = 0; idx < SNDRV_CARDS; idx++) {
                mutex_lock(&snd_card_mutex);
-               if ((card = snd_cards[idx]) != NULL) {
+               card = snd_cards[idx];
+               if (card) {
                        count++;
                        snd_iprintf(buffer, "%2i [%-15s]: %s - %s\n",
                                        idx,
@@ -837,7 +839,8 @@ void snd_card_info_read_oss(struct snd_info_buffer *buffer)
 
        for (idx = count = 0; idx < SNDRV_CARDS; idx++) {
                mutex_lock(&snd_card_mutex);
-               if ((card = snd_cards[idx]) != NULL) {
+               card = snd_cards[idx];
+               if (card) {
                        count++;
                        snd_iprintf(buffer, "%s\n", card->longname);
                }
@@ -859,7 +862,8 @@ static void snd_card_module_info_read(struct snd_info_entry *entry,
 
        for (idx = 0; idx < SNDRV_CARDS; idx++) {
                mutex_lock(&snd_card_mutex);
-               if ((card = snd_cards[idx]) != NULL)
+               card = snd_cards[idx];
+               if (card)
                        snd_iprintf(buffer, "%2i %s\n",
                                    idx, card->module->name);
                mutex_unlock(&snd_card_mutex);
@@ -1002,21 +1006,28 @@ EXPORT_SYMBOL(snd_card_file_remove);
 
 #ifdef CONFIG_PM
 /**
- *  snd_power_wait - wait until the power-state is changed.
- *  @card: soundcard structure
- *  @power_state: expected power state
+ * snd_power_ref_and_wait - wait until the card gets powered up
+ * @card: soundcard structure
+ *
+ * Take the power_ref reference count of the given card, and
+ * wait until the card gets powered up to SNDRV_CTL_POWER_D0 state.
+ * The refcount is down again while sleeping until power-up, hence this
+ * function can be used for syncing the floating control ops accesses,
+ * typically around calling control ops.
  *
- *  Waits until the power-state is changed.
+ * The caller needs to pull down the refcount via snd_power_unref() later
+ * no matter whether the error is returned from this function or not.
  *
- *  Return: Zero if successful, or a negative error code.
+ * Return: Zero if successful, or a negative error code.
  */
-int snd_power_wait(struct snd_card *card, unsigned int power_state)
+int snd_power_ref_and_wait(struct snd_card *card)
 {
        wait_queue_entry_t wait;
        int result = 0;
 
+       snd_power_ref(card);
        /* fastpath */
-       if (snd_power_get_state(card) == power_state)
+       if (snd_power_get_state(card) == SNDRV_CTL_POWER_D0)
                return 0;
        init_waitqueue_entry(&wait, current);
        add_wait_queue(&card->power_sleep, &wait);
@@ -1025,13 +1036,33 @@ int snd_power_wait(struct snd_card *card, unsigned int power_state)
                        result = -ENODEV;
                        break;
                }
-               if (snd_power_get_state(card) == power_state)
+               if (snd_power_get_state(card) == SNDRV_CTL_POWER_D0)
                        break;
+               snd_power_unref(card);
                set_current_state(TASK_UNINTERRUPTIBLE);
                schedule_timeout(30 * HZ);
+               snd_power_ref(card);
        }
        remove_wait_queue(&card->power_sleep, &wait);
        return result;
 }
+EXPORT_SYMBOL_GPL(snd_power_ref_and_wait);
+
+/**
+ * snd_power_wait - wait until the card gets powered up (old form)
+ * @card: soundcard structure
+ *
+ * Wait until the card gets powered up to SNDRV_CTL_POWER_D0 state.
+ *
+ * Return: Zero if successful, or a negative error code.
+ */
+int snd_power_wait(struct snd_card *card)
+{
+       int ret;
+
+       ret = snd_power_ref_and_wait(card);
+       snd_power_unref(card);
+       return ret;
+}
 EXPORT_SYMBOL(snd_power_wait);
 #endif /* CONFIG_PM */