/* 2008-03-06  Lydia Wang  Add VT1702 codec and VT1708S codec support        */
 /* 2008-04-09  Lydia Wang  Add mute front speaker when HP plugin             */
 /* 2008-04-09  Lydia Wang  Add Independent HP feature                        */
+/* 2008-05-28  Lydia Wang  Add second S/PDIF Out support for VT1702         */
 /*                                                                           */
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
        char *stream_name_digital;
        struct hda_pcm_stream *stream_digital_playback;
        struct hda_pcm_stream *stream_digital_capture;
+       struct hda_pcm_stream *stream_extra_digital_playback;
 
        /* playback */
        struct hda_multi_out multiout;
+       hda_nid_t extra_dig_out_nid;
 
        /* capture */
        unsigned int num_adc_nids;
        unsigned int cur_mux[3];
 
        /* PCM information */
-       struct hda_pcm pcm_rec[2];
+       struct hda_pcm pcm_rec[3];
 
        /* dynamic controls, init_verbs and input_mux */
        struct auto_pin_cfg autocfg;
                                             stream_tag, format, substream);
 }
 
+/* setup SPDIF output stream */
+static void setup_dig_playback_stream(struct hda_codec *codec, hda_nid_t nid,
+                                unsigned int stream_tag, unsigned int format)
+{
+       /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
+       if (codec->spdif_ctls & AC_DIG1_ENABLE)
+               snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
+                                   codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
+       snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
+       /* turn on again (if needed) */
+       if (codec->spdif_ctls & AC_DIG1_ENABLE)
+               snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
+                                   codec->spdif_ctls & 0xff);
+}
+
+static int via_extra_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
+                                       struct hda_codec *codec,
+                                       unsigned int stream_tag,
+                                       unsigned int format,
+                                       struct snd_pcm_substream *substream)
+{
+       struct via_spec *spec = codec->spec;
+
+       mutex_lock(&codec->spdif_mutex);
+       setup_dig_playback_stream(codec, spec->extra_dig_out_nid, stream_tag,
+                                 format);
+       mutex_unlock(&codec->spdif_mutex);
+       return 0;
+}
+
 /*
  * Analog capture
  */
                if (err < 0)
                        return err;
                spec->multiout.share_spdif = 1;
+
+               if (spec->extra_dig_out_nid) {
+                       err = snd_hda_create_spdif_out_ctls(codec,
+                                                   spec->extra_dig_out_nid);
+                       if (err < 0)
+                               return err;
+               }
        }
        if (spec->dig_in_nid) {
                err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
                }
        }
 
+       if (spec->extra_dig_out_nid) {
+               codec->num_pcms++;
+               info++;
+               info->name = spec->stream_name_digital;
+               info->pcm_type = HDA_PCM_TYPE_HDMI;
+               info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
+                               *(spec->stream_extra_digital_playback);
+               info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
+                               spec->extra_dig_out_nid;
+       }
+
        return 0;
 }
 
        },
 };
 
+static struct hda_pcm_stream vt1708S_pcm_extra_digital_playback = {
+       .substreams = 1,
+       .channels_min = 2,
+       .channels_max = 2,
+       /* NID is set in via_build_pcms */
+       .ops = {
+               .prepare = via_extra_dig_playback_pcm_prepare
+       },
+};
+
 /* fill in the dac_nids table from the parsed pin configuration */
 static int vt1708S_auto_fill_dac_nids(struct via_spec *spec,
                                     const struct auto_pin_cfg *cfg)
        if (spec->autocfg.dig_out_pin)
                spec->multiout.dig_out_nid = VT1708S_DIGOUT_NID;
 
+       spec->extra_dig_out_nid = 0x15;
+
        if (spec->kctl_alloc)
                spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
 
 
        spec->stream_name_digital = "VT1708S Digital";
        spec->stream_digital_playback = &vt1708S_pcm_digital_playback;
+       spec->stream_extra_digital_playback =
+                                       &vt1708S_pcm_extra_digital_playback;
 
        if (!spec->adc_nids && spec->input_mux) {
                spec->adc_nids = vt1708S_adc_nids;
        },
 };
 
+static struct hda_pcm_stream vt1702_pcm_extra_digital_playback = {
+       .substreams = 1,
+       .channels_min = 2,
+       .channels_max = 2,
+       /* NID is set in via_build_pcms */
+       .ops = {
+               .prepare = via_extra_dig_playback_pcm_prepare
+       },
+};
+
 /* fill in the dac_nids table from the parsed pin configuration */
 static int vt1702_auto_fill_dac_nids(struct via_spec *spec,
                                     const struct auto_pin_cfg *cfg)
        if (spec->autocfg.dig_out_pin)
                spec->multiout.dig_out_nid = VT1702_DIGOUT_NID;
 
+       spec->extra_dig_out_nid = 0x1B;
+
        if (spec->kctl_alloc)
                spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
 
 
        spec->stream_name_digital = "VT1702 Digital";
        spec->stream_digital_playback = &vt1702_pcm_digital_playback;
+       spec->stream_extra_digital_playback =
+                                       &vt1702_pcm_extra_digital_playback;
 
        if (!spec->adc_nids && spec->input_mux) {
                spec->adc_nids = vt1702_adc_nids;