return (unsigned long)(ptr - array->list) / array->elem_size;
 }
 
+/* a helper macro to iterate for each snd_array element */
+#define snd_array_for_each(array, idx, ptr) \
+       for ((idx) = 0, (ptr) = (array)->list; (idx) < (array)->used; \
+            (ptr) = snd_array_elem(array, ++(idx)))
+
 #endif /* __SOUND_HDAUDIO_H */
 
 {
        struct hdac_device *codec = dev_to_hdac_dev(dev);
        unsigned int verb = get_verb(reg);
+       const unsigned int *v;
        int i;
 
-       for (i = 0; i < codec->vendor_verbs.used; i++) {
-               unsigned int *v = snd_array_elem(&codec->vendor_verbs, i);
+       snd_array_for_each(&codec->vendor_verbs, i, v) {
                if (verb == *v)
                        return true;
        }
 
  */
 void snd_hda_apply_verbs(struct hda_codec *codec)
 {
+       const struct hda_verb **v;
        int i;
-       for (i = 0; i < codec->verbs.used; i++) {
-               struct hda_verb **v = snd_array_elem(&codec->verbs, i);
+
+       snd_array_for_each(&codec->verbs, i, v)
                snd_hda_sequence_write(codec, *v);
-       }
 }
 EXPORT_SYMBOL_GPL(snd_hda_apply_verbs);
 
 static bool pin_config_match(struct hda_codec *codec,
                             const struct hda_pintbl *pins)
 {
+       const struct hda_pincfg *pin;
        int i;
 
-       for (i = 0; i < codec->init_pins.used; i++) {
-               struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
+       snd_array_for_each(&codec->init_pins, i, pin) {
                hda_nid_t nid = pin->nid;
                u32 cfg = pin->cfg;
                const struct hda_pintbl *t_pins;
 
                                         struct snd_array *array,
                                         hda_nid_t nid)
 {
+       struct hda_pincfg *pin;
        int i;
-       for (i = 0; i < array->used; i++) {
-               struct hda_pincfg *pin = snd_array_elem(array, i);
+
+       snd_array_for_each(array, i, pin) {
                if (pin->nid == nid)
                        return pin;
        }
  */
 void snd_hda_shutup_pins(struct hda_codec *codec)
 {
+       const struct hda_pincfg *pin;
        int i;
+
        /* don't shut up pins when unloading the driver; otherwise it breaks
         * the default pin setup at the next load of the driver
         */
        if (codec->bus->shutdown)
                return;
-       for (i = 0; i < codec->init_pins.used; i++) {
-               struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
+       snd_array_for_each(&codec->init_pins, i, pin) {
                /* use read here for syncing after issuing each verb */
                snd_hda_codec_read(codec, pin->nid, 0,
                                   AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
 /* Restore the pin controls cleared previously via snd_hda_shutup_pins() */
 static void restore_shutup_pins(struct hda_codec *codec)
 {
+       const struct hda_pincfg *pin;
        int i;
+
        if (!codec->pins_shutup)
                return;
        if (codec->bus->shutdown)
                return;
-       for (i = 0; i < codec->init_pins.used; i++) {
-               struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
+       snd_array_for_each(&codec->init_pins, i, pin) {
                snd_hda_codec_write(codec, pin->nid, 0,
                                    AC_VERB_SET_PIN_WIDGET_CONTROL,
                                    pin->ctrl);
        struct hda_cvt_setup *p;
        int i;
 
-       for (i = 0; i < codec->cvt_setups.used; i++) {
-               p = snd_array_elem(&codec->cvt_setups, i);
+       snd_array_for_each(&codec->cvt_setups, i, p) {
                if (p->nid == nid)
                        return p;
        }
        /* make other inactive cvts with the same stream-tag dirty */
        type = get_wcaps_type(get_wcaps(codec, nid));
        list_for_each_codec(c, codec->bus) {
-               for (i = 0; i < c->cvt_setups.used; i++) {
-                       p = snd_array_elem(&c->cvt_setups, i);
+               snd_array_for_each(&c->cvt_setups, i, p) {
                        if (!p->active && p->stream_tag == stream_tag &&
                            get_wcaps_type(get_wcaps(c, p->nid)) == type)
                                p->dirty = 1;
 static void purify_inactive_streams(struct hda_codec *codec)
 {
        struct hda_codec *c;
+       struct hda_cvt_setup *p;
        int i;
 
        list_for_each_codec(c, codec->bus) {
-               for (i = 0; i < c->cvt_setups.used; i++) {
-                       struct hda_cvt_setup *p;
-                       p = snd_array_elem(&c->cvt_setups, i);
+               snd_array_for_each(&c->cvt_setups, i, p) {
                        if (p->dirty)
                                really_cleanup_stream(c, p);
                }
 /* clean up all streams; called from suspend */
 static void hda_cleanup_all_streams(struct hda_codec *codec)
 {
+       struct hda_cvt_setup *p;
        int i;
 
-       for (i = 0; i < codec->cvt_setups.used; i++) {
-               struct hda_cvt_setup *p = snd_array_elem(&codec->cvt_setups, i);
+       snd_array_for_each(&codec->cvt_setups, i, p) {
                if (p->stream_tag)
                        really_cleanup_stream(codec, p);
        }
 struct hda_spdif_out *snd_hda_spdif_out_of_nid(struct hda_codec *codec,
                                               hda_nid_t nid)
 {
+       struct hda_spdif_out *spdif;
        int i;
-       for (i = 0; i < codec->spdif_out.used; i++) {
-               struct hda_spdif_out *spdif =
-                               snd_array_elem(&codec->spdif_out, i);
+
+       snd_array_for_each(&codec->spdif_out, i, spdif) {
                if (spdif->nid == nid)
                        return spdif;
        }
 
                                     int anchor_nid)
 {
        struct hda_gen_spec *spec = codec->spec;
+       struct nid_path *path;
        int i;
 
-       for (i = 0; i < spec->paths.used; i++) {
-               struct nid_path *path = snd_array_elem(&spec->paths, i);
+       snd_array_for_each(&spec->paths, i, path) {
                if (path->depth <= 0)
                        continue;
                if ((!from_nid || path->path[0] == from_nid) &&
 static bool is_dac_already_used(struct hda_codec *codec, hda_nid_t nid)
 {
        struct hda_gen_spec *spec = codec->spec;
+       const struct nid_path *path;
        int i;
 
-       for (i = 0; i < spec->paths.used; i++) {
-               struct nid_path *path = snd_array_elem(&spec->paths, i);
+       snd_array_for_each(&spec->paths, i, path) {
                if (path->path[0] == nid)
                        return true;
        }
 static bool is_ctl_used(struct hda_codec *codec, unsigned int val, int type)
 {
        struct hda_gen_spec *spec = codec->spec;
+       const struct nid_path *path;
        int i;
 
        val &= AMP_VAL_COMPARE_MASK;
-       for (i = 0; i < spec->paths.used; i++) {
-               struct nid_path *path = snd_array_elem(&spec->paths, i);
+       snd_array_for_each(&spec->paths, i, path) {
                if ((path->ctls[type] & AMP_VAL_COMPARE_MASK) == val)
                        return true;
        }
 {
        struct hda_gen_spec *spec = codec->spec;
        int type = get_wcaps_type(get_wcaps(codec, nid));
+       const struct nid_path *path;
        int i, n;
 
        if (nid == codec->core.afg)
                return true;
 
-       for (n = 0; n < spec->paths.used; n++) {
-               struct nid_path *path = snd_array_elem(&spec->paths, n);
+       snd_array_for_each(&spec->paths, n, path) {
                if (!path->active)
                        continue;
                if (codec->power_save_node) {
 static bool find_kctl_name(struct hda_codec *codec, const char *name, int idx)
 {
        struct hda_gen_spec *spec = codec->spec;
+       const struct snd_kcontrol_new *kctl;
        int i;
 
-       for (i = 0; i < spec->kctls.used; i++) {
-               struct snd_kcontrol_new *kctl = snd_array_elem(&spec->kctls, i);
+       snd_array_for_each(&spec->kctls, i, kctl) {
                if (!strcmp(kctl->name, name) && kctl->index == idx)
                        return true;
        }
        struct nid_path *path;
        int n;
 
-       for (n = 0; n < spec->paths.used; n++) {
-               path = snd_array_elem(&spec->paths, n);
+       snd_array_for_each(&spec->paths, n, path) {
                if (!path->depth)
                        continue;
                if (path->path[0] == nid ||
  */
 static void clear_unsol_on_unused_pins(struct hda_codec *codec)
 {
+       const struct hda_pincfg *pin;
        int i;
 
-       for (i = 0; i < codec->init_pins.used; i++) {
-               struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
+       snd_array_for_each(&codec->init_pins, i, pin) {
                hda_nid_t nid = pin->nid;
                if (is_jack_detectable(codec, nid) &&
                    !snd_hda_jack_tbl_get(codec, nid))
 
                                struct snd_array *list,
                                char *buf)
 {
+       const struct hda_pincfg *pin;
        int i, len = 0;
        mutex_lock(&codec->user_mutex);
-       for (i = 0; i < list->used; i++) {
-               struct hda_pincfg *pin = snd_array_elem(list, i);
+       snd_array_for_each(list, i, pin) {
                len += sprintf(buf + len, "0x%02x 0x%08x\n",
                               pin->nid, pin->cfg);
        }
                               char *buf)
 {
        struct hda_codec *codec = dev_get_drvdata(dev);
+       const struct hda_verb *v;
        int i, len = 0;
        mutex_lock(&codec->user_mutex);
-       for (i = 0; i < codec->init_verbs.used; i++) {
-               struct hda_verb *v = snd_array_elem(&codec->init_verbs, i);
+       snd_array_for_each(&codec->init_verbs, i, v) {
                len += snprintf(buf + len, PAGE_SIZE - len,
                                "0x%02x 0x%03x 0x%04x\n",
                                v->nid, v->verb, v->param);
                          char *buf)
 {
        struct hda_codec *codec = dev_get_drvdata(dev);
+       const struct hda_hint *hint;
        int i, len = 0;
        mutex_lock(&codec->user_mutex);
-       for (i = 0; i < codec->hints.used; i++) {
-               struct hda_hint *hint = snd_array_elem(&codec->hints, i);
+       snd_array_for_each(&codec->hints, i, hint) {
                len += snprintf(buf + len, PAGE_SIZE - len,
                                "%s = %s\n", hint->key, hint->val);
        }
 
 static struct hda_hint *get_hint(struct hda_codec *codec, const char *key)
 {
+       struct hda_hint *hint;
        int i;
 
-       for (i = 0; i < codec->hints.used; i++) {
-               struct hda_hint *hint = snd_array_elem(&codec->hints, i);
+       snd_array_for_each(&codec->hints, i, hint) {
                if (!strcmp(hint->key, key))
                        return hint;
        }
 void snd_hda_sysfs_clear(struct hda_codec *codec)
 {
 #ifdef CONFIG_SND_HDA_RECONFIG
+       struct hda_hint *hint;
        int i;
 
        /* clear init verbs */
        snd_array_free(&codec->init_verbs);
        /* clear hints */
-       for (i = 0; i < codec->hints.used; i++) {
-               struct hda_hint *hint = snd_array_elem(&codec->hints, i);
+       snd_array_for_each(&codec->hints, i, hint) {
                kfree(hint->key); /* we don't need to free hint->val */
        }
        snd_array_free(&codec->hints);
 
                                    const struct hda_fixup *fix, int action)
 {
        struct conexant_spec *spec = codec->spec;
+       struct snd_kcontrol_new *kctl;
        int i;
 
        if (action != HDA_FIXUP_ACT_PROBE)
        snd_hda_codec_set_pin_target(codec, 0x1a, PIN_VREF50);
 
        /* override mic boost control */
-       for (i = 0; i < spec->gen.kctls.used; i++) {
-               struct snd_kcontrol_new *kctl =
-                       snd_array_elem(&spec->gen.kctls, i);
+       snd_array_for_each(&spec->gen.kctls, i, kctl) {
                if (!strcmp(kctl->name, "Mic Boost Volume")) {
                        kctl->put = olpc_xo_mic_boost_put;
                        break;
 
 
 static void alc286_shutup(struct hda_codec *codec)
 {
+       const struct hda_pincfg *pin;
        int i;
        int mic_pin = find_ext_mic_pin(codec);
        /* don't shut up pins when unloading the driver; otherwise it breaks
         */
        if (codec->bus->shutdown)
                return;
-       for (i = 0; i < codec->init_pins.used; i++) {
-               struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
+       snd_array_for_each(&codec->init_pins, i, pin) {
                /* use read here for syncing after issuing each verb */
                if (pin->nid != mic_pin)
                        snd_hda_codec_read(codec, pin->nid, 0,