]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - sound/pci/hda/patch_realtek.c
ALSA: hda - Create beep control on ALC269 codec
[linux-2.6-omap-h63xx.git] / sound / pci / hda / patch_realtek.c
index 909f1c101c95af5e0a1c2db614a946de1cd570be..9cb6b73ef95aafc9201902aad2fda2273429febf 100644 (file)
@@ -100,6 +100,7 @@ enum {
        ALC262_BENQ_T31,
        ALC262_ULTRA,
        ALC262_LENOVO_3000,
+       ALC262_NEC,
        ALC262_AUTO,
        ALC262_MODEL_LAST /* last tag */
 };
@@ -2632,12 +2633,14 @@ static int alc_build_pcms(struct hda_codec *codec)
 
        info->name = spec->stream_name_analog;
        if (spec->stream_analog_playback) {
-               snd_assert(spec->multiout.dac_nids, return -EINVAL);
+               if (snd_BUG_ON(!spec->multiout.dac_nids))
+                       return -EINVAL;
                info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
                info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
        }
        if (spec->stream_analog_capture) {
-               snd_assert(spec->adc_nids, return -EINVAL);
+               if (snd_BUG_ON(!spec->adc_nids))
+                       return -EINVAL;
                info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
                info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
        }
@@ -2667,6 +2670,8 @@ static int alc_build_pcms(struct hda_codec *codec)
                        info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_digital_capture);
                        info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
                }
+               /* FIXME: do we need this for all Realtek codec models? */
+               codec->spdif_status_reset = 1;
        }
 
        /* If the use of more than one ADC is requested for the current
@@ -6197,7 +6202,6 @@ static struct snd_pci_quirk alc882_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x817f, "Asus P5LD2", ALC882_6ST_DIG),
        SND_PCI_QUIRK(0x1043, 0x81d8, "Asus P5WD", ALC882_6ST_DIG),
        SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC882_6ST_DIG),
-       SND_PCI_QUIRK(0x106b, 0x00a0, "Apple iMac 24''", ALC885_IMAC24),
        SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte P35 DS3R", ALC882_6ST_DIG),
        SND_PCI_QUIRK(0x1462, 0x28fb, "Targa T8", ALC882_TARGA), /* MSI-1049 T8  */
        SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC882_6ST_DIG),
@@ -7943,7 +7947,7 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_ACER_ASPIRE),
        SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_ACER_ASPIRE),
        SND_PCI_QUIRK(0x1025, 0x0112, "Acer Aspire 9303", ALC883_ACER_ASPIRE),
-       SND_PCI_QUIRK(0x1025, 0x0121, "Acer Aspire 5920G", ALC883_ACER_ASPIRE), 
+       SND_PCI_QUIRK(0x1025, 0x0121, "Acer Aspire 5920G", ALC883_ACER_ASPIRE),
        SND_PCI_QUIRK(0x1025, 0, "Acer laptop", ALC883_ACER), /* default Acer */
        SND_PCI_QUIRK(0x1028, 0x020d, "Dell Inspiron 530", ALC888_6ST_DELL),
        SND_PCI_QUIRK(0x103c, 0x2a3d, "HP Pavillion", ALC883_6ST_DIG),
@@ -8948,6 +8952,41 @@ static void alc262_hippo1_unsol_event(struct hda_codec *codec,
        alc262_hippo1_automute(codec);
 }
 
+/*
+ * nec model
+ *  0x15 = headphone
+ *  0x16 = internal speaker
+ *  0x18 = external mic
+ */
+
+static struct snd_kcontrol_new alc262_nec_mixer[] = {
+       HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE_MONO("Speaker Playback Switch", 0x16, 0, 0x0, HDA_OUTPUT),
+
+       HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+       HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+       HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
+
+       HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+       { } /* end */
+};
+
+static struct hda_verb alc262_nec_verbs[] = {
+       /* Unmute Speaker */
+       {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+
+       /* Headphone */
+       {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
+       {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+
+       /* External mic to headphone */
+       {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+       /* External mic to speaker */
+       {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+       {}
+};
+
 /*
  * fujitsu model
  *  0x14 = headphone/spdif-out, 0x15 = internal speaker,
@@ -9732,11 +9771,13 @@ static const char *alc262_models[ALC262_MODEL_LAST] = {
        [ALC262_SONY_ASSAMD]    = "sony-assamd",
        [ALC262_ULTRA]          = "ultra",
        [ALC262_LENOVO_3000]    = "lenovo-3000",
+       [ALC262_NEC]            = "nec",
        [ALC262_AUTO]           = "auto",
 };
 
 static struct snd_pci_quirk alc262_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1002, 0x437b, "Hippo", ALC262_HIPPO),
+       SND_PCI_QUIRK(0x1033, 0x8895, "NEC Versa S9100", ALC262_NEC),
        SND_PCI_QUIRK(0x103c, 0x12fe, "HP xw9400", ALC262_HP_BPC),
        SND_PCI_QUIRK(0x103c, 0x12ff, "HP xw4550", ALC262_HP_BPC),
        SND_PCI_QUIRK(0x103c, 0x1306, "HP xw8600", ALC262_HP_BPC),
@@ -9947,6 +9988,16 @@ static struct alc_config_preset alc262_presets[] = {
                .input_mux = &alc262_fujitsu_capture_source,
                .unsol_event = alc262_lenovo_3000_unsol_event,
        },
+       [ALC262_NEC] = {
+               .mixers = { alc262_nec_mixer },
+               .init_verbs = { alc262_nec_verbs },
+               .num_dacs = ARRAY_SIZE(alc262_dac_nids),
+               .dac_nids = alc262_dac_nids,
+               .hp_nid = 0x03,
+               .num_channel_mode = ARRAY_SIZE(alc262_modes),
+               .channel_mode = alc262_modes,
+               .input_mux = &alc262_capture_source,
+       },
 };
 
 static int patch_alc262(struct hda_codec *codec)
@@ -11017,6 +11068,8 @@ static struct snd_kcontrol_new alc269_base_mixer[] = {
        HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
        HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
        HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+       HDA_CODEC_VOLUME("Beep Playback Volume", 0x0b, 0x4, HDA_INPUT),
+       HDA_CODEC_MUTE("Beep Playback Switch", 0x0b, 0x4, HDA_INPUT),
        HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
        HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
        HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
@@ -11069,6 +11122,13 @@ static struct snd_kcontrol_new alc269_epc_capture_mixer[] = {
        { } /* end */
 };
 
+/* beep control */
+static struct snd_kcontrol_new alc269_beep_mixer[] = {
+       HDA_CODEC_VOLUME("Beep Playback Volume", 0x0b, 0x4, HDA_INPUT),
+       HDA_CODEC_MUTE("Beep Playback Switch", 0x0b, 0x4, HDA_INPUT),
+       { } /* end */
+};
+
 /*
  * generic initialization of ADC, input mixers and output mixers
  */
@@ -11331,7 +11391,7 @@ static int alc269_auto_create_multi_out_ctls(struct alc_spec *spec,
 static int alc269_parse_auto_config(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       int err;
+       int i, err;
        static hda_nid_t alc269_ignore[] = { 0x1d, 0 };
 
        err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
@@ -11354,6 +11414,13 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
        if (spec->kctl_alloc)
                spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
 
+       /* create a beep mixer control if the pin 0x1d isn't assigned */
+       for (i = 0; i < ARRAY_SIZE(spec->autocfg.input_pins); i++)
+               if (spec->autocfg.input_pins[i] == 0x1d)
+                       break;
+       if (i >= ARRAY_SIZE(spec->autocfg.input_pins))
+               spec->mixers[spec->num_mixers++] = alc269_beep_mixer;
+
        spec->init_verbs[spec->num_init_verbs++] = alc269_init_verbs;
        spec->num_mux_defs = 1;
        spec->input_mux = &spec->private_imux;
@@ -14067,6 +14134,13 @@ static struct hda_verb alc662_auto_init_verbs[] = {
        { }
 };
 
+/* additional verbs for ALC663 */
+static struct hda_verb alc663_auto_init_verbs[] = {
+       {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+       {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+       { }
+};
+
 static struct hda_verb alc663_m51va_init_verbs[] = {
        {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
        {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
@@ -14595,6 +14669,14 @@ static int alc662_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin,
        if (!pin)
                return 0;
 
+       if (pin == 0x17) {
+               /* ALC663 has a mono output pin on 0x17 */
+               sprintf(name, "%s Playback Switch", pfx);
+               err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
+                                 HDA_COMPOSE_AMP_VAL(pin, 2, 0, HDA_OUTPUT));
+               return err;
+       }
+
        if (alc880_is_fixed_pin(pin)) {
                nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
                 /* printk("DAC nid=%x\n",nid); */
@@ -14765,6 +14847,14 @@ static int alc662_parse_auto_config(struct hda_codec *codec)
        spec->input_mux = &spec->private_imux;
        
        spec->init_verbs[spec->num_init_verbs++] = alc662_auto_init_verbs;
+       if (codec->vendor_id == 0x10ec0663)
+               spec->init_verbs[spec->num_init_verbs++] =
+                       alc663_auto_init_verbs;
+
+       err = alc_auto_add_mic_boost(codec);
+       if (err < 0)
+               return err;
+
        spec->mixers[spec->num_mixers] = alc662_capture_mixer;
        spec->num_mixers++;
        return 1;