]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - sound/pci/hda/patch_sigmatel.c
[ALSA] hda-codec - Add support of AD1883/1884A/1984A/1984B
[linux-2.6-omap-h63xx.git] / sound / pci / hda / patch_sigmatel.c
index caf48edaa921f629870b5e39bc4e83a94d56c52d..7901e76f269066753b5eec6b6cd7012b8a22c326 100644 (file)
@@ -39,6 +39,7 @@
 
 enum {
        STAC_REF,
+       STAC_9200_OQO,
        STAC_9200_DELL_D21,
        STAC_9200_DELL_D22,
        STAC_9200_DELL_D23,
@@ -135,6 +136,7 @@ struct sigmatel_spec {
        /* power management */
        unsigned int num_pwrs;
        hda_nid_t *pwr_nids;
+       hda_nid_t *dac_list;
 
        /* playback */
        struct hda_input_mux *mono_mux;
@@ -290,6 +292,10 @@ static hda_nid_t stac927x_mux_nids[3] = {
         0x15, 0x16, 0x17
 };
 
+static hda_nid_t stac927x_dac_nids[6] = {
+       0x02, 0x03, 0x04, 0x05, 0x06, 0
+};
+
 static hda_nid_t stac927x_dmux_nids[1] = {
        0x1b,
 };
@@ -910,6 +916,11 @@ static int stac92xx_build_controls(struct hda_codec *codec)
                err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
                if (err < 0)
                        return err;
+               err = snd_hda_create_spdif_share_sw(codec,
+                                                   &spec->multiout);
+               if (err < 0)
+                       return err;
+               spec->multiout.share_spdif = 1;
        }
        if (spec->dig_in_nid) {
                err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
@@ -1052,9 +1063,15 @@ static unsigned int dell9200_m27_pin_configs[8] = {
        0x90170310, 0x04a11020, 0x90170310, 0x40f003fc,
 };
 
+static unsigned int oqo9200_pin_configs[8] = {
+       0x40c000f0, 0x404000f1, 0x0221121f, 0x02211210,
+       0x90170111, 0x90a70120, 0x400000f2, 0x400000f3,
+};
+
 
 static unsigned int *stac9200_brd_tbl[STAC_9200_MODELS] = {
        [STAC_REF] = ref9200_pin_configs,
+       [STAC_9200_OQO] = oqo9200_pin_configs,
        [STAC_9200_DELL_D21] = dell9200_d21_pin_configs,
        [STAC_9200_DELL_D22] = dell9200_d22_pin_configs,
        [STAC_9200_DELL_D23] = dell9200_d23_pin_configs,
@@ -1069,6 +1086,7 @@ static unsigned int *stac9200_brd_tbl[STAC_9200_MODELS] = {
 
 static const char *stac9200_models[STAC_9200_MODELS] = {
        [STAC_REF] = "ref",
+       [STAC_9200_OQO] = "oqo",
        [STAC_9200_DELL_D21] = "dell-d21",
        [STAC_9200_DELL_D22] = "dell-d22",
        [STAC_9200_DELL_D23] = "dell-d23",
@@ -1153,6 +1171,8 @@ static struct snd_pci_quirk stac9200_cfg_tbl[] = {
                      STAC_9200_GATEWAY),
        SND_PCI_QUIRK(0x107b, 0x0318, "Gateway ML3019, MT3707",
                      STAC_9200_GATEWAY),
+       /* OQO Mobile */
+       SND_PCI_QUIRK(0x1106, 0x3288, "OQO Model 2", STAC_9200_OQO),
        {} /* terminator */
 };
 
@@ -1733,7 +1753,8 @@ static int stac92xx_playback_pcm_open(struct hda_pcm_stream *hinfo,
                                      struct snd_pcm_substream *substream)
 {
        struct sigmatel_spec *spec = codec->spec;
-       return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
+       return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
+                                            hinfo);
 }
 
 static int stac92xx_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
@@ -1889,6 +1910,7 @@ static int stac92xx_build_pcms(struct hda_codec *codec)
                codec->num_pcms++;
                info++;
                info->name = "STAC92xx Digital";
+               info->pcm_type = HDA_PCM_TYPE_SPDIF;
                if (spec->multiout.dig_out_nid) {
                        info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_digital_playback;
                        info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
@@ -2866,6 +2888,18 @@ static int is_nid_hp_pin(struct auto_pin_cfg *cfg, hda_nid_t nid)
        return 0; /* nid is not a HP-Out */
 };
 
+static void stac92xx_power_down(struct hda_codec *codec)
+{
+       struct sigmatel_spec *spec = codec->spec;
+
+       /* power down inactive DACs */
+       hda_nid_t *dac;
+       for (dac = spec->dac_list; *dac; dac++)
+               if (!is_in_dac_nids(spec, *dac))
+                       snd_hda_codec_write_cache(codec, *dac, 0,
+                                       AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+}
+
 static int stac92xx_init(struct hda_codec *codec)
 {
        struct sigmatel_spec *spec = codec->spec;
@@ -2918,7 +2952,8 @@ static int stac92xx_init(struct hda_codec *codec)
                enable_pin_detect(codec, spec->pwr_nids[i], event | i);
                codec->patch_ops.unsol_event(codec, (event | i) << 26);
        }
-
+       if (spec->dac_list)
+               stac92xx_power_down(codec);
        if (cfg->dig_out_pin)
                stac92xx_auto_set_pinctl(codec, cfg->dig_out_pin,
                                         AC_PINCTL_OUT_EN);
@@ -3091,6 +3126,9 @@ static int stac92xx_resume(struct hda_codec *codec)
                spec->gpio_dir, spec->gpio_data);
        snd_hda_codec_resume_amp(codec);
        snd_hda_codec_resume_cache(codec);
+       /* power down inactive DACs */
+       if (spec->dac_list)
+               stac92xx_power_down(codec);
        /* invoke unsolicited event to reset the HP state */
        if (spec->hp_detect)
                codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26);
@@ -3147,7 +3185,8 @@ static int patch_stac9200(struct hda_codec *codec)
        spec->num_adcs = 1;
        spec->num_pwrs = 0;
 
-       if (spec->board_config == STAC_9200_GATEWAY)
+       if (spec->board_config == STAC_9200_GATEWAY ||
+           spec->board_config == STAC_9200_OQO)
                spec->init = stac9200_eapd_init;
        else
                spec->init = stac9200_core_init;
@@ -3577,6 +3616,7 @@ static int patch_stac927x(struct hda_codec *codec)
        spec->num_adcs = ARRAY_SIZE(stac927x_adc_nids);
        spec->mux_nids = stac927x_mux_nids;
        spec->num_muxes = ARRAY_SIZE(stac927x_mux_nids);
+       spec->dac_list = stac927x_dac_nids;
        spec->multiout.dac_nids = spec->dac_nids;
 
        switch (spec->board_config) {