]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 28 Jul 2011 12:49:31 +0000 (05:49 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 28 Jul 2011 12:49:31 +0000 (05:49 -0700)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6:
  sound: oss: rename local change_bits to avoid powerpc bitsops.h definition
  ALSA: hda - Fix duplicated DAC assignments for Realtek
  ALSA: asihpi - off by one in asihpi_hpi_ioctl()
  ALSA: hda - Fix Oops with Realtek quirks with NULL adc_nids
  ALSA: asihpi - bug fix pa use before init.
  ALSA: hda - Add support for vref-out based mute LED control on IDT codecs

sound/oss/ad1848.c
sound/oss/sb_mixer.c
sound/pci/asihpi/hpioctl.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c

index 4d2a6ae978f720baa57faa391b665b060018da47..8a197fd3c57e07602156d11f3acd1debe33e504c 100644 (file)
@@ -458,7 +458,7 @@ static int ad1848_set_recmask(ad1848_info * devc, int mask)
        return mask;
 }
 
-static void change_bits(ad1848_info * devc, unsigned char *regval,
+static void oss_change_bits(ad1848_info *devc, unsigned char *regval,
                        unsigned char *muteval, int dev, int chn, int newval)
 {
        unsigned char mask;
@@ -516,10 +516,10 @@ static void ad1848_mixer_set_channel(ad1848_info *devc, int dev, int value, int
 
        if (muteregoffs != regoffs) {
                muteval = ad_read(devc, muteregoffs);
-               change_bits(devc, &val, &muteval, dev, channel, value);
+               oss_change_bits(devc, &val, &muteval, dev, channel, value);
        }
        else
-               change_bits(devc, &val, &val, dev, channel, value);
+               oss_change_bits(devc, &val, &val, dev, channel, value);
 
        spin_lock_irqsave(&devc->lock,flags);
        ad_write(devc, regoffs, val);
index 2039d31b7e2248f25fdf3b38c81f264e1669ed4e..f8f3b7a66b7377fcc25fc84b76c8b9b63af44181 100644 (file)
@@ -232,7 +232,7 @@ static int detect_mixer(sb_devc * devc)
        return 1;
 }
 
-static void change_bits(sb_devc * devc, unsigned char *regval, int dev, int chn, int newval)
+static void oss_change_bits(sb_devc *devc, unsigned char *regval, int dev, int chn, int newval)
 {
        unsigned char mask;
        int shift;
@@ -284,7 +284,7 @@ int sb_common_mixer_set(sb_devc * devc, int dev, int left, int right)
                return -EINVAL;
 
        val = sb_getmixer(devc, regoffs);
-       change_bits(devc, &val, dev, LEFT_CHN, left);
+       oss_change_bits(devc, &val, dev, LEFT_CHN, left);
 
        if ((*devc->iomap)[dev][RIGHT_CHN].regno != regoffs)    /*
                                                                 * Change register
@@ -304,7 +304,7 @@ int sb_common_mixer_set(sb_devc * devc, int dev, int left, int right)
                                                         * Read the new one
                                                         */
        }
-       change_bits(devc, &val, dev, RIGHT_CHN, right);
+       oss_change_bits(devc, &val, dev, RIGHT_CHN, right);
 
        sb_setmixer(devc, regoffs, val);
 
index 65fcf4770731d1e0fa5606112f3c741f38dab7b0..9683f84ecdc835ea964932e358b4a66bcbc6a628 100644 (file)
@@ -107,7 +107,6 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        union hpi_response_buffer_v1 *hr;
        u16 res_max_size;
        u32 uncopied_bytes;
-       struct hpi_adapter *pa = NULL;
        int err = 0;
 
        if (cmd != HPI_IOCTL_LINUX)
@@ -182,8 +181,9 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                /* -1=no data 0=read from user mem, 1=write to user mem */
                int wrflag = -1;
                u32 adapter = hm->h.adapter_index;
+               struct hpi_adapter *pa = &adapters[adapter];
 
-               if ((adapter > HPI_MAX_ADAPTERS) || (!pa->type)) {
+               if ((adapter >= HPI_MAX_ADAPTERS) || (!pa->type)) {
                        hpi_init_response(&hr->r0, HPI_OBJ_ADAPTER,
                                HPI_ADAPTER_OPEN,
                                HPI_ERROR_BAD_ADAPTER_NUMBER);
@@ -197,9 +197,7 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                        goto out;
                }
 
-               pa = &adapters[adapter];
-
-               if (mutex_lock_interruptible(&adapters[adapter].mutex)) {
+               if (mutex_lock_interruptible(&pa->mutex)) {
                        err = -EINTR;
                        goto out;
                }
@@ -235,8 +233,7 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                                                        "stream buffer size %d\n",
                                                        size);
 
-                                               mutex_unlock(&adapters
-                                                       [adapter].mutex);
+                                               mutex_unlock(&pa->mutex);
                                                err = -EINVAL;
                                                goto out;
                                        }
@@ -277,7 +274,7 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                                        uncopied_bytes, size);
                }
 
-               mutex_unlock(&adapters[adapter].mutex);
+               mutex_unlock(&pa->mutex);
        }
 
        /* on return response size must be set */
index 694327ae8b718523eeafc2731743f1573aa63fe3..e125c60fe3527abafd690c6825c19c57956c8265 100644 (file)
@@ -895,13 +895,15 @@ static void alc_init_auto_hp(struct hda_codec *codec)
        if (present == 3)
                spec->automute_hp_lo = 1; /* both HP and LO automute */
 
-       if (!cfg->speaker_pins[0]) {
+       if (!cfg->speaker_pins[0] &&
+           cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
                memcpy(cfg->speaker_pins, cfg->line_out_pins,
                       sizeof(cfg->speaker_pins));
                cfg->speaker_outs = cfg->line_outs;
        }
 
-       if (!cfg->hp_pins[0]) {
+       if (!cfg->hp_pins[0] &&
+           cfg->line_out_type == AUTO_PIN_HP_OUT) {
                memcpy(cfg->hp_pins, cfg->line_out_pins,
                       sizeof(cfg->hp_pins));
                cfg->hp_outs = cfg->line_outs;
@@ -920,6 +922,7 @@ static void alc_init_auto_hp(struct hda_codec *codec)
                spec->automute_mode = ALC_AUTOMUTE_PIN;
        }
        if (spec->automute && cfg->line_out_pins[0] &&
+           cfg->speaker_pins[0] &&
            cfg->line_out_pins[0] != cfg->hp_pins[0] &&
            cfg->line_out_pins[0] != cfg->speaker_pins[0]) {
                for (i = 0; i < cfg->line_outs; i++) {
@@ -1911,7 +1914,7 @@ static int alc_build_controls(struct hda_codec *codec)
                                return err;
                }
        }
-       if (spec->cap_mixer) {
+       if (spec->cap_mixer && spec->adc_nids) {
                const char *kname = kctl ? kctl->id.name : NULL;
                for (knew = spec->cap_mixer; knew->name; knew++) {
                        if (kname && strcmp(knew->name, kname) == 0)
@@ -3677,7 +3680,7 @@ static int patch_alc880(struct hda_codec *codec)
        if (board_config != ALC_MODEL_AUTO)
                setup_preset(codec, &alc880_presets[board_config]);
 
-       if (!spec->no_analog && !spec->adc_nids && spec->input_mux) {
+       if (!spec->no_analog && !spec->adc_nids) {
                alc_auto_fill_adc_caps(codec);
                alc_rebuild_imux_for_auto_mic(codec);
                alc_remove_invalid_adc_nids(codec);
@@ -3804,7 +3807,7 @@ static int patch_alc260(struct hda_codec *codec)
        if (board_config != ALC_MODEL_AUTO)
                setup_preset(codec, &alc260_presets[board_config]);
 
-       if (!spec->no_analog && !spec->adc_nids && spec->input_mux) {
+       if (!spec->no_analog && !spec->adc_nids) {
                alc_auto_fill_adc_caps(codec);
                alc_rebuild_imux_for_auto_mic(codec);
                alc_remove_invalid_adc_nids(codec);
@@ -3983,7 +3986,7 @@ static int patch_alc882(struct hda_codec *codec)
        if (board_config != ALC_MODEL_AUTO)
                setup_preset(codec, &alc882_presets[board_config]);
 
-       if (!spec->no_analog && !spec->adc_nids && spec->input_mux) {
+       if (!spec->no_analog && !spec->adc_nids) {
                alc_auto_fill_adc_caps(codec);
                alc_rebuild_imux_for_auto_mic(codec);
                alc_remove_invalid_adc_nids(codec);
@@ -4137,7 +4140,7 @@ static int patch_alc262(struct hda_codec *codec)
        if (board_config != ALC_MODEL_AUTO)
                setup_preset(codec, &alc262_presets[board_config]);
 
-       if (!spec->no_analog && !spec->adc_nids && spec->input_mux) {
+       if (!spec->no_analog && !spec->adc_nids) {
                alc_auto_fill_adc_caps(codec);
                alc_rebuild_imux_for_auto_mic(codec);
                alc_remove_invalid_adc_nids(codec);
@@ -4293,7 +4296,7 @@ static int patch_alc268(struct hda_codec *codec)
                                          (0 << AC_AMPCAP_MUTE_SHIFT));
        }
 
-       if (!spec->no_analog && !spec->adc_nids && spec->input_mux) {
+       if (!spec->no_analog && !spec->adc_nids) {
                alc_auto_fill_adc_caps(codec);
                alc_rebuild_imux_for_auto_mic(codec);
                alc_remove_invalid_adc_nids(codec);
@@ -4705,7 +4708,7 @@ static int patch_alc269(struct hda_codec *codec)
        if (board_config != ALC_MODEL_AUTO)
                setup_preset(codec, &alc269_presets[board_config]);
 
-       if (!spec->no_analog && !spec->adc_nids && spec->input_mux) {
+       if (!spec->no_analog && !spec->adc_nids) {
                alc_auto_fill_adc_caps(codec);
                alc_rebuild_imux_for_auto_mic(codec);
                alc_remove_invalid_adc_nids(codec);
@@ -4843,7 +4846,7 @@ static int patch_alc861(struct hda_codec *codec)
        if (board_config != ALC_MODEL_AUTO)
                setup_preset(codec, &alc861_presets[board_config]);
 
-       if (!spec->no_analog && !spec->adc_nids && spec->input_mux) {
+       if (!spec->no_analog && !spec->adc_nids) {
                alc_auto_fill_adc_caps(codec);
                alc_rebuild_imux_for_auto_mic(codec);
                alc_remove_invalid_adc_nids(codec);
@@ -4984,7 +4987,7 @@ static int patch_alc861vd(struct hda_codec *codec)
                add_verb(spec, alc660vd_eapd_verbs);
        }
 
-       if (!spec->no_analog && !spec->adc_nids && spec->input_mux) {
+       if (!spec->no_analog && !spec->adc_nids) {
                alc_auto_fill_adc_caps(codec);
                alc_rebuild_imux_for_auto_mic(codec);
                alc_remove_invalid_adc_nids(codec);
@@ -5200,7 +5203,7 @@ static int patch_alc662(struct hda_codec *codec)
        if (board_config != ALC_MODEL_AUTO)
                setup_preset(codec, &alc662_presets[board_config]);
 
-       if (!spec->no_analog && !spec->adc_nids && spec->input_mux) {
+       if (!spec->no_analog && !spec->adc_nids) {
                alc_auto_fill_adc_caps(codec);
                alc_rebuild_imux_for_auto_mic(codec);
                alc_remove_invalid_adc_nids(codec);
@@ -5336,7 +5339,7 @@ static int patch_alc680(struct hda_codec *codec)
 #endif
        }
 
-       if (!spec->no_analog && !spec->adc_nids && spec->input_mux) {
+       if (!spec->no_analog && !spec->adc_nids) {
                alc_auto_fill_adc_caps(codec);
                alc_rebuild_imux_for_auto_mic(codec);
                alc_remove_invalid_adc_nids(codec);
index fcf4c7142103366a290a8efa2055565434154027..aa376b59c006227f0f9be4a6349abb8ac4dff6d5 100644 (file)
@@ -213,6 +213,7 @@ struct sigmatel_spec {
        unsigned int gpio_mute;
        unsigned int gpio_led;
        unsigned int gpio_led_polarity;
+       unsigned int vref_led;
 
        /* stream */
        unsigned int stream_delay;
@@ -672,6 +673,30 @@ static int stac92xx_smux_enum_put(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
+static int stac_vrefout_set(struct hda_codec *codec,
+                                       hda_nid_t nid, unsigned int new_vref)
+{
+       int error, pinctl;
+
+       snd_printdd("%s, nid %x ctl %x\n", __func__, nid, new_vref);
+       pinctl = snd_hda_codec_read(codec, nid, 0,
+                               AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+
+       if (pinctl < 0)
+               return pinctl;
+
+       pinctl &= 0xff;
+       pinctl &= ~AC_PINCTL_VREFEN;
+       pinctl |= (new_vref & AC_PINCTL_VREFEN);
+
+       error = snd_hda_codec_write_cache(codec, nid, 0,
+                                       AC_VERB_SET_PIN_WIDGET_CONTROL, pinctl);
+       if (error < 0)
+               return error;
+
+       return 1;
+}
+
 static unsigned int stac92xx_vref_set(struct hda_codec *codec,
                                        hda_nid_t nid, unsigned int new_vref)
 {
@@ -4069,6 +4094,8 @@ static void stac_gpio_set(struct hda_codec *codec, unsigned int mask,
 {
        unsigned int gpiostate, gpiomask, gpiodir;
 
+       snd_printdd("%s msk %x dir %x gpio %x\n", __func__, mask, dir_mask, data);
+
        gpiostate = snd_hda_codec_read(codec, codec->afg, 0,
                                       AC_VERB_GET_GPIO_DATA, 0);
        gpiostate = (gpiostate & ~dir_mask) | (data & dir_mask);
@@ -4258,10 +4285,12 @@ static void stac_store_hints(struct hda_codec *codec)
                spec->eapd_switch = val;
        get_int_hint(codec, "gpio_led_polarity", &spec->gpio_led_polarity);
        if (get_int_hint(codec, "gpio_led", &spec->gpio_led)) {
-               spec->gpio_mask |= spec->gpio_led;
-               spec->gpio_dir |= spec->gpio_led;
-               if (spec->gpio_led_polarity)
-                       spec->gpio_data |= spec->gpio_led;
+               if (spec->gpio_led <= 8) {
+                       spec->gpio_mask |= spec->gpio_led;
+                       spec->gpio_dir |= spec->gpio_led;
+                       if (spec->gpio_led_polarity)
+                               spec->gpio_data |= spec->gpio_led;
+               }
        }
 }
 
@@ -4431,11 +4460,26 @@ static void stac92xx_free_kctls(struct hda_codec *codec)
        snd_array_free(&spec->kctls);
 }
 
+static void stac92xx_shutup_pins(struct hda_codec *codec)
+{
+       unsigned int i, def_conf;
+
+       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);
+               def_conf = snd_hda_codec_get_pincfg(codec, pin->nid);
+               if (get_defcfg_connect(def_conf) != AC_JACK_PORT_NONE)
+                       snd_hda_codec_write(codec, pin->nid, 0,
+                                   AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
+       }
+}
+
 static void stac92xx_shutup(struct hda_codec *codec)
 {
        struct sigmatel_spec *spec = codec->spec;
 
-       snd_hda_shutup_pins(codec);
+       stac92xx_shutup_pins(codec);
 
        if (spec->eapd_mask)
                stac_gpio_set(codec, spec->gpio_mask,
@@ -4833,10 +4877,11 @@ static int find_mute_led_gpio(struct hda_codec *codec, int default_polarity)
        if ((codec->subsystem_id >> 16) == PCI_VENDOR_ID_HP) {
                while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING,
                                                                NULL, dev))) {
-                       if (sscanf(dev->name, "HP_Mute_LED_%d_%d",
+                       if (sscanf(dev->name, "HP_Mute_LED_%d_%x",
                                  &spec->gpio_led_polarity,
                                  &spec->gpio_led) == 2) {
-                               spec->gpio_led = 1 << spec->gpio_led;
+                               if (spec->gpio_led < 4)
+                                       spec->gpio_led = 1 << spec->gpio_led;
                                return 1;
                        }
                        if (sscanf(dev->name, "HP_Mute_LED_%d",
@@ -4935,17 +4980,6 @@ static void stac927x_proc_hook(struct snd_info_buffer *buffer,
 #endif
 
 #ifdef CONFIG_PM
-static int stac92xx_pre_resume(struct hda_codec *codec)
-{
-       struct sigmatel_spec *spec = codec->spec;
-
-       /* sync mute LED */
-       if (spec->gpio_led)
-               stac_gpio_set(codec, spec->gpio_mask,
-                               spec->gpio_dir, spec->gpio_data);
-       return 0;
-}
-
 static int stac92xx_resume(struct hda_codec *codec)
 {
        struct sigmatel_spec *spec = codec->spec;
@@ -4964,7 +4998,65 @@ static int stac92xx_resume(struct hda_codec *codec)
        return 0;
 }
 
+static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state)
+{
+       stac92xx_shutup(codec);
+       return 0;
+}
+
 #ifdef CONFIG_SND_HDA_POWER_SAVE
+static int stac92xx_pre_resume(struct hda_codec *codec)
+{
+       struct sigmatel_spec *spec = codec->spec;
+
+       /* sync mute LED */
+       if (spec->gpio_led) {
+               if (spec->gpio_led <= 8) {
+                       stac_gpio_set(codec, spec->gpio_mask,
+                                       spec->gpio_dir, spec->gpio_data);
+               } else {
+                       stac_vrefout_set(codec,
+                                       spec->gpio_led, spec->vref_led);
+               }
+       }
+       return 0;
+}
+
+static int stac92xx_post_suspend(struct hda_codec *codec)
+{
+       struct sigmatel_spec *spec = codec->spec;
+       if (spec->gpio_led > 8) {
+               /* with vref-out pin used for mute led control
+                * codec AFG is prevented from D3 state, but on
+                * system suspend it can (and should) be used
+                */
+               snd_hda_codec_read(codec, codec->afg, 0,
+                               AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+       }
+       return 0;
+}
+
+static void stac92xx_set_power_state(struct hda_codec *codec, hda_nid_t fg,
+                               unsigned int power_state)
+{
+       unsigned int afg_power_state = power_state;
+       struct sigmatel_spec *spec = codec->spec;
+
+       if (power_state == AC_PWRST_D3) {
+               if (spec->gpio_led > 8) {
+                       /* with vref-out pin used for mute led control
+                        * codec AFG is prevented from D3 state
+                        */
+                       afg_power_state = AC_PWRST_D1;
+               }
+               /* this delay seems necessary to avoid click noise at power-down */
+               msleep(100);
+       }
+       snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE,
+                       afg_power_state);
+       snd_hda_codec_set_power_to_all(codec, fg, power_state, true);
+}
+
 /*
  * For this feature CONFIG_SND_HDA_POWER_SAVE is needed
  * as mute LED state is updated in check_power_status hook
@@ -4973,8 +5065,12 @@ static int stac92xx_update_led_status(struct hda_codec *codec)
 {
        struct sigmatel_spec *spec = codec->spec;
        int i, num_ext_dacs, muted = 1;
+       unsigned int muted_lvl, notmtd_lvl;
        hda_nid_t nid;
 
+       if (!spec->gpio_led)
+               return 0;
+
        for (i = 0; i < spec->multiout.num_dacs; i++) {
                nid = spec->multiout.dac_nids[i];
                if (!(snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) &
@@ -4999,17 +5095,27 @@ static int stac92xx_update_led_status(struct hda_codec *codec)
                        muted = 0; /* extra output is not muted */
                }
        }
-       if (muted)
-               spec->gpio_data &= ~spec->gpio_led; /* orange */
-       else
-               spec->gpio_data |= spec->gpio_led; /* white */
+       /*polarity defines *not* muted state level*/
+       if (spec->gpio_led <= 8) {
+               if (muted)
+                       spec->gpio_data &= ~spec->gpio_led; /* orange */
+               else
+                       spec->gpio_data |= spec->gpio_led; /* white */
 
-       if (!spec->gpio_led_polarity) {
-               /* LED state is inverted on these systems */
-               spec->gpio_data ^= spec->gpio_led;
+               if (!spec->gpio_led_polarity) {
+                       /* LED state is inverted on these systems */
+                       spec->gpio_data ^= spec->gpio_led;
+               }
+               stac_gpio_set(codec, spec->gpio_mask,
+                               spec->gpio_dir, spec->gpio_data);
+       } else {
+               notmtd_lvl = spec->gpio_led_polarity ?
+                               AC_PINCTL_VREF_HIZ : AC_PINCTL_VREF_GRD;
+               muted_lvl = spec->gpio_led_polarity ?
+                               AC_PINCTL_VREF_GRD : AC_PINCTL_VREF_HIZ;
+               spec->vref_led = muted ? muted_lvl : notmtd_lvl;
+               stac_vrefout_set(codec, spec->gpio_led, spec->vref_led);
        }
-
-       stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data);
        return 0;
 }
 
@@ -5023,13 +5129,7 @@ static int stac92xx_check_power_status(struct hda_codec *codec,
 
        return 0;
 }
-#endif
-
-static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state)
-{
-       stac92xx_shutup(codec);
-       return 0;
-}
+#endif /* CONFIG_SND_HDA_POWER_SAVE */
 #endif /* CONFIG_PM */
 
 static const struct hda_codec_ops stac92xx_patch_ops = {
@@ -5041,7 +5141,6 @@ static const struct hda_codec_ops stac92xx_patch_ops = {
 #ifdef CONFIG_PM
        .suspend = stac92xx_suspend,
        .resume = stac92xx_resume,
-       .pre_resume = stac92xx_pre_resume,
 #endif
        .reboot_notify = stac92xx_shutup,
 };
@@ -5555,10 +5654,17 @@ again:
 
 #ifdef CONFIG_SND_HDA_POWER_SAVE
        if (spec->gpio_led) {
-               spec->gpio_mask |= spec->gpio_led;
-               spec->gpio_dir |= spec->gpio_led;
-               spec->gpio_data |= spec->gpio_led;
-               /* register check_power_status callback. */
+               if (spec->gpio_led <= 8) {
+                       spec->gpio_mask |= spec->gpio_led;
+                       spec->gpio_dir |= spec->gpio_led;
+                       spec->gpio_data |= spec->gpio_led;
+               } else {
+                       codec->patch_ops.set_power_state =
+                                       stac92xx_set_power_state;
+                       codec->patch_ops.post_suspend =
+                                       stac92xx_post_suspend;
+               }
+               codec->patch_ops.pre_resume = stac92xx_pre_resume;
                codec->patch_ops.check_power_status =
                        stac92xx_check_power_status;
        }
@@ -5883,10 +5989,17 @@ again:
 
 #ifdef CONFIG_SND_HDA_POWER_SAVE
        if (spec->gpio_led) {
-               spec->gpio_mask |= spec->gpio_led;
-               spec->gpio_dir |= spec->gpio_led;
-               spec->gpio_data |= spec->gpio_led;
-               /* register check_power_status callback. */
+               if (spec->gpio_led <= 8) {
+                       spec->gpio_mask |= spec->gpio_led;
+                       spec->gpio_dir |= spec->gpio_led;
+                       spec->gpio_data |= spec->gpio_led;
+               } else {
+                       codec->patch_ops.set_power_state =
+                                       stac92xx_set_power_state;
+                       codec->patch_ops.post_suspend =
+                                       stac92xx_post_suspend;
+               }
+               codec->patch_ops.pre_resume = stac92xx_pre_resume;
                codec->patch_ops.check_power_status =
                        stac92xx_check_power_status;
        }