Merge branch 'test/hda-vol-ofs' into next/hda
authorTakashi Iwai <tiwai@suse.de>
Thu, 22 Jan 2009 07:33:04 +0000 (08:33 +0100)
committerTakashi Iwai <tiwai@suse.de>
Thu, 22 Jan 2009 07:33:04 +0000 (08:33 +0100)
1  2 
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_local.h
sound/pci/hda/patch_sigmatel.c

index dd419ce43d92f216a089d9b80e7ed02ef0a66e0d,0cf2424ada6a0063a185b9364e466746d61820ce..a259b3eb4f733f3e6e8fd6eefdeb0356edf9dae2
@@@ -1119,6 -1119,7 +1119,7 @@@ int snd_hda_mixer_amp_volume_info(struc
        u16 nid = get_amp_nid(kcontrol);
        u8 chs = get_amp_channels(kcontrol);
        int dir = get_amp_direction(kcontrol);
+       unsigned int ofs = get_amp_offset(kcontrol);
        u32 caps;
  
        caps = query_amp_caps(codec, nid, dir);
                       kcontrol->id.name);
                return -EINVAL;
        }
+       if (ofs < caps)
+               caps -= ofs;
        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
        uinfo->count = chs == 3 ? 2 : 1;
        uinfo->value.integer.min = 0;
  }
  EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info);
  
+ static inline unsigned int
+ read_amp_value(struct hda_codec *codec, hda_nid_t nid,
+              int ch, int dir, int idx, unsigned int ofs)
+ {
+       unsigned int val;
+       val = snd_hda_codec_amp_read(codec, nid, ch, dir, idx);
+       val &= HDA_AMP_VOLMASK;
+       if (val >= ofs)
+               val -= ofs;
+       else
+               val = 0;
+       return val;
+ }
+ static inline int
+ update_amp_value(struct hda_codec *codec, hda_nid_t nid,
+                int ch, int dir, int idx, unsigned int ofs,
+                unsigned int val)
+ {
+       if (val > 0)
+               val += ofs;
+       return snd_hda_codec_amp_update(codec, nid, ch, dir, idx,
+                                       HDA_AMP_VOLMASK, val);
+ }
  int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
                                 struct snd_ctl_elem_value *ucontrol)
  {
        int chs = get_amp_channels(kcontrol);
        int dir = get_amp_direction(kcontrol);
        int idx = get_amp_index(kcontrol);
+       unsigned int ofs = get_amp_offset(kcontrol);
        long *valp = ucontrol->value.integer.value;
  
        if (chs & 1)
-               *valp++ = snd_hda_codec_amp_read(codec, nid, 0, dir, idx)
-                       & HDA_AMP_VOLMASK;
+               *valp++ = read_amp_value(codec, nid, 0, dir, idx, ofs);
        if (chs & 2)
-               *valp = snd_hda_codec_amp_read(codec, nid, 1, dir, idx)
-                       & HDA_AMP_VOLMASK;
+               *valp = read_amp_value(codec, nid, 1, dir, idx, ofs);
        return 0;
  }
  EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_get);
@@@ -1166,18 -1194,17 +1194,17 @@@ int snd_hda_mixer_amp_volume_put(struc
        int chs = get_amp_channels(kcontrol);
        int dir = get_amp_direction(kcontrol);
        int idx = get_amp_index(kcontrol);
+       unsigned int ofs = get_amp_offset(kcontrol);
        long *valp = ucontrol->value.integer.value;
        int change = 0;
  
        snd_hda_power_up(codec);
        if (chs & 1) {
-               change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
-                                                 0x7f, *valp);
+               change = update_amp_value(codec, nid, 0, dir, idx, ofs, *valp);
                valp++;
        }
        if (chs & 2)
-               change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx,
-                                                  0x7f, *valp);
+               change |= update_amp_value(codec, nid, 1, dir, idx, ofs, *valp);
        snd_hda_power_down(codec);
        return change;
  }
@@@ -1189,6 -1216,7 +1216,7 @@@ int snd_hda_mixer_amp_tlv(struct snd_kc
        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
        hda_nid_t nid = get_amp_nid(kcontrol);
        int dir = get_amp_direction(kcontrol);
+       unsigned int ofs = get_amp_offset(kcontrol);
        u32 caps, val1, val2;
  
        if (size < 4 * sizeof(unsigned int))
        val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
        val2 = (val2 + 1) * 25;
        val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT);
+       val1 += ofs;
        val1 = ((int)val1) * ((int)val2);
        if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv))
                return -EFAULT;
@@@ -2613,7 -2642,7 +2642,7 @@@ int snd_hda_codec_build_pcms(struct hda
                int dev;
  
                if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams)
 -                      return 0; /* no substreams assigned */
 +                      continue; /* no substreams assigned */
  
                if (!cpcm->pcm) {
                        dev = get_empty_pcm_device(codec->bus, cpcm->pcm_type);
@@@ -3390,20 -3419,10 +3419,20 @@@ int snd_hda_parse_pin_def_config(struc
                        cfg->input_pins[AUTO_PIN_AUX] = nid;
                        break;
                case AC_JACK_SPDIF_OUT:
 +              case AC_JACK_DIG_OTHER_OUT:
                        cfg->dig_out_pin = nid;
 +                      if (loc == AC_JACK_LOC_HDMI)
 +                              cfg->dig_out_type = HDA_PCM_TYPE_HDMI;
 +                      else
 +                              cfg->dig_out_type = HDA_PCM_TYPE_SPDIF;
                        break;
                case AC_JACK_SPDIF_IN:
 +              case AC_JACK_DIG_OTHER_IN:
                        cfg->dig_in_pin = nid;
 +                      if (loc == AC_JACK_LOC_HDMI)
 +                              cfg->dig_in_type = HDA_PCM_TYPE_HDMI;
 +                      else
 +                              cfg->dig_in_type = HDA_PCM_TYPE_SPDIF;
                        break;
                }
        }
                   cfg->hp_pins[1], cfg->hp_pins[2],
                   cfg->hp_pins[3], cfg->hp_pins[4]);
        snd_printd("   mono: mono_out=0x%x\n", cfg->mono_out_pin);
 +      if (cfg->dig_out_pin)
 +              snd_printd("   dig-out=0x%x\n", cfg->dig_out_pin);
        snd_printd("   inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x,"
                   " cd=0x%x, aux=0x%x\n",
                   cfg->input_pins[AUTO_PIN_MIC],
                   cfg->input_pins[AUTO_PIN_FRONT_LINE],
                   cfg->input_pins[AUTO_PIN_CD],
                   cfg->input_pins[AUTO_PIN_AUX]);
 +      if (cfg->dig_out_pin)
 +              snd_printd("   dig-in=0x%x\n", cfg->dig_in_pin);
  
        return 0;
  }
index a4ecd77a451a1c0b314a533e1b926782ee8bd27f,d53ce1f854190476f5e6fb8e6fd1a32d88338cb8..ec687b206c0a51c66ddfb61e3dd541f55d934748
  /*
   * for mixer controls
   */
+ #define HDA_COMPOSE_AMP_VAL_OFS(nid,chs,idx,dir,ofs)          \
+       ((nid) | ((chs)<<16) | ((dir)<<18) | ((idx)<<19) | ((ofs)<<23))
  #define HDA_COMPOSE_AMP_VAL(nid,chs,idx,dir) \
-       ((nid) | ((chs)<<16) | ((dir)<<18) | ((idx)<<19))
+       HDA_COMPOSE_AMP_VAL_OFS(nid, chs, idx, dir, 0)
  /* mono volume with index (index=0,1,...) (channel=1,2) */
  #define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \
        { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx,  \
@@@ -355,8 -357,6 +357,8 @@@ struct auto_pin_cfg 
        hda_nid_t dig_out_pin;
        hda_nid_t dig_in_pin;
        hda_nid_t mono_out_pin;
 +      int dig_out_type; /* HDA_PCM_TYPE_XXX */
 +      int dig_in_type; /* HDA_PCM_TYPE_XXX */
  };
  
  #define get_defcfg_connect(cfg) \
@@@ -458,6 -458,7 +460,7 @@@ int snd_hda_check_amp_list_power(struc
  #define get_amp_channels(kc)  (((kc)->private_value >> 16) & 0x3)
  #define get_amp_direction(kc) (((kc)->private_value >> 18) & 0x1)
  #define get_amp_index(kc)     (((kc)->private_value >> 19) & 0xf)
+ #define get_amp_offset(kc)    (((kc)->private_value >> 23) & 0x3f)
  
  /*
   * CEA Short Audio Descriptor data
index dbe8b1201eff4922604d459e20774c6f4fbb48ea,c2d4abee3b0963089fdfdddba4bad970cafb4a58..0fa6c593d1d3625f2c68abb2453ff98af9d55282
@@@ -166,6 -166,7 +166,7 @@@ struct sigmatel_spec 
        unsigned int alt_switch: 1;
        unsigned int hp_detect: 1;
        unsigned int spdif_mute: 1;
+       unsigned int check_volume_offset:1;
  
        /* gpio lines */
        unsigned int eapd_mask;
        hda_nid_t hp_dacs[5];
        hda_nid_t speaker_dacs[5];
  
+       int volume_offset;
        /* capture */
        hda_nid_t *adc_nids;
        unsigned int num_adcs;
@@@ -841,6 -844,10 +844,6 @@@ static struct hda_verb stac92hd73xx_10c
  };
  
  static struct hda_verb stac92hd83xxx_core_init[] = {
 -      /* start of config #1 */
 -      { 0xe, AC_VERB_SET_CONNECT_SEL, 0x3},
 -
 -      /* start of config #2 */
        { 0xa, AC_VERB_SET_CONNECT_SEL, 0x0},
        { 0xb, AC_VERB_SET_CONNECT_SEL, 0x0},
        { 0xd, AC_VERB_SET_CONNECT_SEL, 0x1},
@@@ -1293,6 -1300,8 +1296,8 @@@ static int stac92xx_build_controls(stru
                unsigned int vmaster_tlv[4];
                snd_hda_set_vmaster_tlv(codec, spec->multiout.dac_nids[0],
                                        HDA_OUTPUT, vmaster_tlv);
+               /* correct volume offset */
+               vmaster_tlv[2] += vmaster_tlv[3] * spec->volume_offset;
                err = snd_hda_add_vmaster(codec, "Master Playback Volume",
                                          vmaster_tlv, slave_vols);
                if (err < 0)
@@@ -2549,7 -2558,7 +2554,7 @@@ static int stac92xx_build_pcms(struct h
                codec->num_pcms++;
                info++;
                info->name = "STAC92xx Digital";
 -              info->pcm_type = HDA_PCM_TYPE_SPDIF;
 +              info->pcm_type = spec->autocfg.dig_out_type;
                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;
@@@ -2976,14 -2985,34 +2981,34 @@@ static int stac92xx_auto_fill_dac_nids(
  }
  
  /* create volume control/switch for the given prefx type */
- static int create_controls(struct sigmatel_spec *spec, const char *pfx, hda_nid_t nid, int chs)
+ static int create_controls(struct hda_codec *codec, const char *pfx,
+                          hda_nid_t nid, int chs)
  {
+       struct sigmatel_spec *spec = codec->spec;
        char name[32];
        int err;
  
+       if (!spec->check_volume_offset) {
+               unsigned int caps, step, nums, db_scale;
+               caps = query_amp_caps(codec, nid, HDA_OUTPUT);
+               step = (caps & AC_AMPCAP_STEP_SIZE) >>
+                       AC_AMPCAP_STEP_SIZE_SHIFT;
+               step = (step + 1) * 25; /* in .01dB unit */
+               nums = (caps & AC_AMPCAP_NUM_STEPS) >>
+                       AC_AMPCAP_NUM_STEPS_SHIFT;
+               db_scale = nums * step;
+               /* if dB scale is over -64dB, and finer enough,
+                * let's reduce it to half
+                */
+               if (db_scale > 6400 && nums >= 0x1f)
+                       spec->volume_offset = nums / 2;
+               spec->check_volume_offset = 1;
+       }
        sprintf(name, "%s Playback Volume", pfx);
        err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, name,
-                                  HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT));
+               HDA_COMPOSE_AMP_VAL_OFS(nid, chs, 0, HDA_OUTPUT,
+                                       spec->volume_offset));
        if (err < 0)
                return err;
        sprintf(name, "%s Playback Switch", pfx);
@@@ -3049,10 -3078,10 +3074,10 @@@ static int stac92xx_auto_create_multi_o
                nid = spec->multiout.dac_nids[i];
                if (i == 2) {
                        /* Center/LFE */
-                       err = create_controls(spec, "Center", nid, 1);
+                       err = create_controls(codec, "Center", nid, 1);
                        if (err < 0)
                                return err;
-                       err = create_controls(spec, "LFE", nid, 2);
+                       err = create_controls(codec, "LFE", nid, 2);
                        if (err < 0)
                                return err;
  
                                        break;
                                }
                        }
-                       err = create_controls(spec, name, nid, 3);
+                       err = create_controls(codec, name, nid, 3);
                        if (err < 0)
                                return err;
                }
@@@ -3135,7 -3164,7 +3160,7 @@@ static int stac92xx_auto_create_hp_ctls
                nid = spec->hp_dacs[i];
                if (!nid)
                        continue;
-               err = create_controls(spec, pfxs[nums++], nid, 3);
+               err = create_controls(codec, pfxs[nums++], nid, 3);
                if (err < 0)
                        return err;
        }
                nid = spec->speaker_dacs[i];
                if (!nid)
                        continue;
-               err = create_controls(spec, pfxs[nums++], nid, 3);
+               err = create_controls(codec, pfxs[nums++], nid, 3);
                if (err < 0)
                        return err;
        }
@@@ -3725,7 -3754,7 +3750,7 @@@ static int stac9200_auto_create_lfe_ctl
        }
  
        if (lfe_pin) {
-               err = create_controls(spec, "LFE", lfe_pin, 1);
+               err = create_controls(codec, "LFE", lfe_pin, 1);
                if (err < 0)
                        return err;
        }
@@@ -4750,9 -4779,7 +4775,9 @@@ static struct hda_input_mux stac92hd83x
  static int patch_stac92hd83xxx(struct hda_codec *codec)
  {
        struct sigmatel_spec *spec;
 +      hda_nid_t conn[STAC92HD83_DAC_COUNT + 1];
        int err;
 +      int num_dacs;
  
        spec  = kzalloc(sizeof(*spec), GFP_KERNEL);
        if (spec == NULL)
        spec->num_pwrs = ARRAY_SIZE(stac92hd83xxx_pwr_nids);
        spec->multiout.dac_nids = spec->dac_nids;
  
 +
 +      /* set port 0xe to select the last DAC
 +       */
 +      num_dacs = snd_hda_get_connections(codec, 0x0e,
 +              conn, STAC92HD83_DAC_COUNT + 1) - 1;
 +
 +      snd_hda_codec_write_cache(codec, 0xe, 0,
 +              AC_VERB_SET_CONNECT_SEL, num_dacs);
 +
        spec->init = stac92hd83xxx_core_init;
        switch (codec->vendor_id) {
        case 0x111d7605:
                break;
        default:
                spec->num_pwrs--;
 -              spec->init++; /* switch to config #2 */
        }
  
        spec->mixer = stac92hd83xxx_mixer;
@@@ -5351,65 -5370,223 +5376,65 @@@ static int patch_stac9205(struct hda_co
   * STAC9872 hack
   */
  
 -/* static config for Sony VAIO FE550G and Sony VAIO AR */
 -static hda_nid_t vaio_dacs[] = { 0x2 };
 -#define VAIO_HP_DAC   0x5
 -static hda_nid_t vaio_adcs[] = { 0x8 /*,0x6*/ };
 -static hda_nid_t vaio_mux_nids[] = { 0x15 };
 -
 -static struct hda_input_mux vaio_mux = {
 -      .num_items = 3,
 -      .items = {
 -              /* { "HP", 0x0 }, */
 -              { "Mic Jack", 0x1 },
 -              { "Internal Mic", 0x2 },
 -              { "PCM", 0x3 },
 -      }
 -};
 -
 -static struct hda_verb vaio_init[] = {
 -      {0x0a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP <- 0x2 */
 -      {0x0a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | STAC_HP_EVENT},
 -      {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Speaker <- 0x5 */
 -      {0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? (<- 0x2) */
 -      {0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD */
 -      {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? */
 -      {0x15, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mic-sel: 0a,0d,14,02 */
 -      {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* HP */
 -      {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Speaker */
 -      {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* capture sw/vol -> 0x8 */
 -      {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, /* CD-in -> 0x6 */
 -      {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Mic-in -> 0x9 */
 -      {}
 -};
 -
 -static struct hda_verb vaio_ar_init[] = {
 -      {0x0a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP <- 0x2 */
 -      {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Speaker <- 0x5 */
 -      {0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? (<- 0x2) */
 -      {0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD */
 -/*    {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },*/ /* Optical Out */
 -      {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? */
 +static struct hda_verb stac9872_core_init[] = {
        {0x15, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mic-sel: 0a,0d,14,02 */
 -      {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* HP */
 -      {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Speaker */
 -/*    {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},*/ /* Optical Out */
 -      {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* capture sw/vol -> 0x8 */
 -      {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, /* CD-in -> 0x6 */
        {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Mic-in -> 0x9 */
        {}
  };
  
 -static struct snd_kcontrol_new vaio_mixer[] = {
 -      HDA_CODEC_VOLUME("Headphone Playback Volume", 0x02, 0, HDA_OUTPUT),
 -      HDA_CODEC_MUTE("Headphone Playback Switch", 0x02, 0, HDA_OUTPUT),
 -      HDA_CODEC_VOLUME("Speaker Playback Volume", 0x05, 0, HDA_OUTPUT),
 -      HDA_CODEC_MUTE("Speaker Playback Switch", 0x05, 0, HDA_OUTPUT),
 -      /* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */
 -      HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT),
 -      HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT),
 -      {
 -              .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 -              .name = "Capture Source",
 -              .count = 1,
 -              .info = stac92xx_mux_enum_info,
 -              .get = stac92xx_mux_enum_get,
 -              .put = stac92xx_mux_enum_put,
 -      },
 -      {}
 -};
 -
 -static struct snd_kcontrol_new vaio_ar_mixer[] = {
 -      HDA_CODEC_VOLUME("Headphone Playback Volume", 0x02, 0, HDA_OUTPUT),
 -      HDA_CODEC_MUTE("Headphone Playback Switch", 0x02, 0, HDA_OUTPUT),
 -      HDA_CODEC_VOLUME("Speaker Playback Volume", 0x05, 0, HDA_OUTPUT),
 -      HDA_CODEC_MUTE("Speaker Playback Switch", 0x05, 0, HDA_OUTPUT),
 -      /* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */
 +static struct snd_kcontrol_new stac9872_mixer[] = {
        HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT),
        HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT),
 -      /*HDA_CODEC_MUTE("Optical Out Switch", 0x10, 0, HDA_OUTPUT),
 -      HDA_CODEC_VOLUME("Optical Out Volume", 0x10, 0, HDA_OUTPUT),*/
 -      {
 -              .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 -              .name = "Capture Source",
 -              .count = 1,
 -              .info = stac92xx_mux_enum_info,
 -              .get = stac92xx_mux_enum_get,
 -              .put = stac92xx_mux_enum_put,
 -      },
 -      {}
 -};
 -
 -static struct hda_codec_ops stac9872_patch_ops = {
 -      .build_controls = stac92xx_build_controls,
 -      .build_pcms = stac92xx_build_pcms,
 -      .init = stac92xx_init,
 -      .free = stac92xx_free,
 -#ifdef SND_HDA_NEEDS_RESUME
 -      .resume = stac92xx_resume,
 -#endif
 -};
 -
 -static int stac9872_vaio_init(struct hda_codec *codec)
 -{
 -      int err;
 -
 -      err = stac92xx_init(codec);
 -      if (err < 0)
 -              return err;
 -      if (codec->patch_ops.unsol_event)
 -              codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26);
 -      return 0;
 -}
 -
 -static void stac9872_vaio_hp_detect(struct hda_codec *codec, unsigned int res)
 -{
 -      if (get_pin_presence(codec, 0x0a)) {
 -              stac92xx_reset_pinctl(codec, 0x0f, AC_PINCTL_OUT_EN);
 -              stac92xx_set_pinctl(codec, 0x0a, AC_PINCTL_OUT_EN);
 -      } else {
 -              stac92xx_reset_pinctl(codec, 0x0a, AC_PINCTL_OUT_EN);
 -              stac92xx_set_pinctl(codec, 0x0f, AC_PINCTL_OUT_EN);
 -      }
 -} 
 -
 -static void stac9872_vaio_unsol_event(struct hda_codec *codec, unsigned int res)
 -{
 -      switch (res >> 26) {
 -      case STAC_HP_EVENT:
 -              stac9872_vaio_hp_detect(codec, res);
 -              break;
 -      }
 -}
 -
 -static struct hda_codec_ops stac9872_vaio_patch_ops = {
 -      .build_controls = stac92xx_build_controls,
 -      .build_pcms = stac92xx_build_pcms,
 -      .init = stac9872_vaio_init,
 -      .free = stac92xx_free,
 -      .unsol_event = stac9872_vaio_unsol_event,
 -#ifdef CONFIG_PM
 -      .resume = stac92xx_resume,
 -#endif
 +      STAC_INPUT_SOURCE(1),
 +      { } /* end */
  };
  
 -enum { /* FE and SZ series. id=0x83847661 and subsys=0x104D0700 or 104D1000. */
 -       CXD9872RD_VAIO,
 -       /* Unknown. id=0x83847662 and subsys=0x104D1200 or 104D1000. */
 -       STAC9872AK_VAIO, 
 -       /* Unknown. id=0x83847661 and subsys=0x104D1200. */
 -       STAC9872K_VAIO,
 -       /* AR Series. id=0x83847664 and subsys=104D1300 */
 -       CXD9872AKD_VAIO,
 -       STAC_9872_MODELS,
 +static hda_nid_t stac9872_pin_nids[] = {
 +      0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
 +      0x11, 0x13, 0x14,
  };
  
 -static const char *stac9872_models[STAC_9872_MODELS] = {
 -      [CXD9872RD_VAIO]        = "vaio",
 -      [CXD9872AKD_VAIO]       = "vaio-ar",
 +static hda_nid_t stac9872_adc_nids[] = {
 +      0x8 /*,0x6*/
  };
  
 -static struct snd_pci_quirk stac9872_cfg_tbl[] = {
 -      SND_PCI_QUIRK(0x104d, 0x81e6, "Sony VAIO F/S", CXD9872RD_VAIO),
 -      SND_PCI_QUIRK(0x104d, 0x81ef, "Sony VAIO F/S", CXD9872RD_VAIO),
 -      SND_PCI_QUIRK(0x104d, 0x81fd, "Sony VAIO AR", CXD9872AKD_VAIO),
 -      SND_PCI_QUIRK(0x104d, 0x8205, "Sony VAIO AR", CXD9872AKD_VAIO),
 -      {}
 +static hda_nid_t stac9872_mux_nids[] = {
 +      0x15
  };
  
  static int patch_stac9872(struct hda_codec *codec)
  {
        struct sigmatel_spec *spec;
 -      int board_config;
 +      int err;
  
 -      board_config = snd_hda_check_board_config(codec, STAC_9872_MODELS,
 -                                                stac9872_models,
 -                                                stac9872_cfg_tbl);
 -      if (board_config < 0)
 -              /* unknown config, let generic-parser do its job... */
 -              return snd_hda_parse_generic_codec(codec);
 -      
        spec  = kzalloc(sizeof(*spec), GFP_KERNEL);
        if (spec == NULL)
                return -ENOMEM;
 -
        codec->spec = spec;
 -      switch (board_config) {
 -      case CXD9872RD_VAIO:
 -      case STAC9872AK_VAIO:
 -      case STAC9872K_VAIO:
 -              spec->mixer = vaio_mixer;
 -              spec->init = vaio_init;
 -              spec->multiout.max_channels = 2;
 -              spec->multiout.num_dacs = ARRAY_SIZE(vaio_dacs);
 -              spec->multiout.dac_nids = vaio_dacs;
 -              spec->multiout.hp_nid = VAIO_HP_DAC;
 -              spec->num_adcs = ARRAY_SIZE(vaio_adcs);
 -              spec->adc_nids = vaio_adcs;
 -              spec->num_pwrs = 0;
 -              spec->input_mux = &vaio_mux;
 -              spec->mux_nids = vaio_mux_nids;
 -              codec->patch_ops = stac9872_vaio_patch_ops;
 -              break;
 -      
 -      case CXD9872AKD_VAIO:
 -              spec->mixer = vaio_ar_mixer;
 -              spec->init = vaio_ar_init;
 -              spec->multiout.max_channels = 2;
 -              spec->multiout.num_dacs = ARRAY_SIZE(vaio_dacs);
 -              spec->multiout.dac_nids = vaio_dacs;
 -              spec->multiout.hp_nid = VAIO_HP_DAC;
 -              spec->num_adcs = ARRAY_SIZE(vaio_adcs);
 -              spec->num_pwrs = 0;
 -              spec->adc_nids = vaio_adcs;
 -              spec->input_mux = &vaio_mux;
 -              spec->mux_nids = vaio_mux_nids;
 -              codec->patch_ops = stac9872_patch_ops;
 -              break;
 -      }
  
 +#if 0 /* no model right now */
 +      spec->board_config = snd_hda_check_board_config(codec, STAC_9872_MODELS,
 +                                                      stac9872_models,
 +                                                      stac9872_cfg_tbl);
 +#endif
 +
 +      spec->num_pins = ARRAY_SIZE(stac9872_pin_nids);
 +      spec->pin_nids = stac9872_pin_nids;
 +      spec->multiout.dac_nids = spec->dac_nids;
 +      spec->num_adcs = ARRAY_SIZE(stac9872_adc_nids);
 +      spec->adc_nids = stac9872_adc_nids;
 +      spec->num_muxes = ARRAY_SIZE(stac9872_mux_nids);
 +      spec->mux_nids = stac9872_mux_nids;
 +      spec->mixer = stac9872_mixer;
 +      spec->init = stac9872_core_init;
 +
 +      err = stac92xx_parse_auto_config(codec, 0x10, 0x12);
 +      if (err < 0) {
 +              stac92xx_free(codec);
 +              return -EINVAL;
 +      }
 +      spec->input_mux = &spec->private_imux;
 +      codec->patch_ops = stac92xx_patch_ops;
        return 0;
  }