aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/sound/alsa/HD-Audio-Models.txt4
-rw-r--r--sound/pci/hda/hda_codec.c61
-rw-r--r--sound/pci/hda/hda_local.h7
-rw-r--r--sound/pci/hda/patch_realtek.c49
-rw-r--r--sound/pci/hda/patch_sigmatel.c301
5 files changed, 189 insertions, 233 deletions
diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt
index 0f5d26bea80f..c9df9db5835a 100644
--- a/Documentation/sound/alsa/HD-Audio-Models.txt
+++ b/Documentation/sound/alsa/HD-Audio-Models.txt
@@ -285,6 +285,7 @@ STAC9205/9254
285 dell-m42 Dell (unknown) 285 dell-m42 Dell (unknown)
286 dell-m43 Dell Precision 286 dell-m43 Dell Precision
287 dell-m44 Dell Inspiron 287 dell-m44 Dell Inspiron
288 eapd Keep EAPD on (e.g. Gateway T1616)
288 289
289STAC9220/9221 290STAC9220/9221
290============= 291=============
@@ -353,5 +354,4 @@ STAC92HD83*
353 354
354STAC9872 355STAC9872
355======== 356========
356 vaio Setup for VAIO FE550G/SZ110 357 N/A
357 vaio-ar Setup for VAIO AR
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index b7bba7dc7cf1..a259b3eb4f73 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -1119,6 +1119,7 @@ int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
1119 u16 nid = get_amp_nid(kcontrol); 1119 u16 nid = get_amp_nid(kcontrol);
1120 u8 chs = get_amp_channels(kcontrol); 1120 u8 chs = get_amp_channels(kcontrol);
1121 int dir = get_amp_direction(kcontrol); 1121 int dir = get_amp_direction(kcontrol);
1122 unsigned int ofs = get_amp_offset(kcontrol);
1122 u32 caps; 1123 u32 caps;
1123 1124
1124 caps = query_amp_caps(codec, nid, dir); 1125 caps = query_amp_caps(codec, nid, dir);
@@ -1130,6 +1131,8 @@ int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
1130 kcontrol->id.name); 1131 kcontrol->id.name);
1131 return -EINVAL; 1132 return -EINVAL;
1132 } 1133 }
1134 if (ofs < caps)
1135 caps -= ofs;
1133 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 1136 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1134 uinfo->count = chs == 3 ? 2 : 1; 1137 uinfo->count = chs == 3 ? 2 : 1;
1135 uinfo->value.integer.min = 0; 1138 uinfo->value.integer.min = 0;
@@ -1138,6 +1141,32 @@ int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
1138} 1141}
1139EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info); 1142EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info);
1140 1143
1144
1145static inline unsigned int
1146read_amp_value(struct hda_codec *codec, hda_nid_t nid,
1147 int ch, int dir, int idx, unsigned int ofs)
1148{
1149 unsigned int val;
1150 val = snd_hda_codec_amp_read(codec, nid, ch, dir, idx);
1151 val &= HDA_AMP_VOLMASK;
1152 if (val >= ofs)
1153 val -= ofs;
1154 else
1155 val = 0;
1156 return val;
1157}
1158
1159static inline int
1160update_amp_value(struct hda_codec *codec, hda_nid_t nid,
1161 int ch, int dir, int idx, unsigned int ofs,
1162 unsigned int val)
1163{
1164 if (val > 0)
1165 val += ofs;
1166 return snd_hda_codec_amp_update(codec, nid, ch, dir, idx,
1167 HDA_AMP_VOLMASK, val);
1168}
1169
1141int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol, 1170int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
1142 struct snd_ctl_elem_value *ucontrol) 1171 struct snd_ctl_elem_value *ucontrol)
1143{ 1172{
@@ -1146,14 +1175,13 @@ int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
1146 int chs = get_amp_channels(kcontrol); 1175 int chs = get_amp_channels(kcontrol);
1147 int dir = get_amp_direction(kcontrol); 1176 int dir = get_amp_direction(kcontrol);
1148 int idx = get_amp_index(kcontrol); 1177 int idx = get_amp_index(kcontrol);
1178 unsigned int ofs = get_amp_offset(kcontrol);
1149 long *valp = ucontrol->value.integer.value; 1179 long *valp = ucontrol->value.integer.value;
1150 1180
1151 if (chs & 1) 1181 if (chs & 1)
1152 *valp++ = snd_hda_codec_amp_read(codec, nid, 0, dir, idx) 1182 *valp++ = read_amp_value(codec, nid, 0, dir, idx, ofs);
1153 & HDA_AMP_VOLMASK;
1154 if (chs & 2) 1183 if (chs & 2)
1155 *valp = snd_hda_codec_amp_read(codec, nid, 1, dir, idx) 1184 *valp = read_amp_value(codec, nid, 1, dir, idx, ofs);
1156 & HDA_AMP_VOLMASK;
1157 return 0; 1185 return 0;
1158} 1186}
1159EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_get); 1187EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_get);
@@ -1166,18 +1194,17 @@ int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
1166 int chs = get_amp_channels(kcontrol); 1194 int chs = get_amp_channels(kcontrol);
1167 int dir = get_amp_direction(kcontrol); 1195 int dir = get_amp_direction(kcontrol);
1168 int idx = get_amp_index(kcontrol); 1196 int idx = get_amp_index(kcontrol);
1197 unsigned int ofs = get_amp_offset(kcontrol);
1169 long *valp = ucontrol->value.integer.value; 1198 long *valp = ucontrol->value.integer.value;
1170 int change = 0; 1199 int change = 0;
1171 1200
1172 snd_hda_power_up(codec); 1201 snd_hda_power_up(codec);
1173 if (chs & 1) { 1202 if (chs & 1) {
1174 change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx, 1203 change = update_amp_value(codec, nid, 0, dir, idx, ofs, *valp);
1175 0x7f, *valp);
1176 valp++; 1204 valp++;
1177 } 1205 }
1178 if (chs & 2) 1206 if (chs & 2)
1179 change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx, 1207 change |= update_amp_value(codec, nid, 1, dir, idx, ofs, *valp);
1180 0x7f, *valp);
1181 snd_hda_power_down(codec); 1208 snd_hda_power_down(codec);
1182 return change; 1209 return change;
1183} 1210}
@@ -1189,6 +1216,7 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1189 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 1216 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1190 hda_nid_t nid = get_amp_nid(kcontrol); 1217 hda_nid_t nid = get_amp_nid(kcontrol);
1191 int dir = get_amp_direction(kcontrol); 1218 int dir = get_amp_direction(kcontrol);
1219 unsigned int ofs = get_amp_offset(kcontrol);
1192 u32 caps, val1, val2; 1220 u32 caps, val1, val2;
1193 1221
1194 if (size < 4 * sizeof(unsigned int)) 1222 if (size < 4 * sizeof(unsigned int))
@@ -1197,6 +1225,7 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1197 val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT; 1225 val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
1198 val2 = (val2 + 1) * 25; 1226 val2 = (val2 + 1) * 25;
1199 val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT); 1227 val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT);
1228 val1 += ofs;
1200 val1 = ((int)val1) * ((int)val2); 1229 val1 = ((int)val1) * ((int)val2);
1201 if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv)) 1230 if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv))
1202 return -EFAULT; 1231 return -EFAULT;
@@ -2613,7 +2642,7 @@ int snd_hda_codec_build_pcms(struct hda_codec *codec)
2613 int dev; 2642 int dev;
2614 2643
2615 if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams) 2644 if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams)
2616 return 0; /* no substreams assigned */ 2645 continue; /* no substreams assigned */
2617 2646
2618 if (!cpcm->pcm) { 2647 if (!cpcm->pcm) {
2619 dev = get_empty_pcm_device(codec->bus, cpcm->pcm_type); 2648 dev = get_empty_pcm_device(codec->bus, cpcm->pcm_type);
@@ -3390,10 +3419,20 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
3390 cfg->input_pins[AUTO_PIN_AUX] = nid; 3419 cfg->input_pins[AUTO_PIN_AUX] = nid;
3391 break; 3420 break;
3392 case AC_JACK_SPDIF_OUT: 3421 case AC_JACK_SPDIF_OUT:
3422 case AC_JACK_DIG_OTHER_OUT:
3393 cfg->dig_out_pin = nid; 3423 cfg->dig_out_pin = nid;
3424 if (loc == AC_JACK_LOC_HDMI)
3425 cfg->dig_out_type = HDA_PCM_TYPE_HDMI;
3426 else
3427 cfg->dig_out_type = HDA_PCM_TYPE_SPDIF;
3394 break; 3428 break;
3395 case AC_JACK_SPDIF_IN: 3429 case AC_JACK_SPDIF_IN:
3430 case AC_JACK_DIG_OTHER_IN:
3396 cfg->dig_in_pin = nid; 3431 cfg->dig_in_pin = nid;
3432 if (loc == AC_JACK_LOC_HDMI)
3433 cfg->dig_in_type = HDA_PCM_TYPE_HDMI;
3434 else
3435 cfg->dig_in_type = HDA_PCM_TYPE_SPDIF;
3397 break; 3436 break;
3398 } 3437 }
3399 } 3438 }
@@ -3499,6 +3538,8 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
3499 cfg->hp_pins[1], cfg->hp_pins[2], 3538 cfg->hp_pins[1], cfg->hp_pins[2],
3500 cfg->hp_pins[3], cfg->hp_pins[4]); 3539 cfg->hp_pins[3], cfg->hp_pins[4]);
3501 snd_printd(" mono: mono_out=0x%x\n", cfg->mono_out_pin); 3540 snd_printd(" mono: mono_out=0x%x\n", cfg->mono_out_pin);
3541 if (cfg->dig_out_pin)
3542 snd_printd(" dig-out=0x%x\n", cfg->dig_out_pin);
3502 snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x," 3543 snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x,"
3503 " cd=0x%x, aux=0x%x\n", 3544 " cd=0x%x, aux=0x%x\n",
3504 cfg->input_pins[AUTO_PIN_MIC], 3545 cfg->input_pins[AUTO_PIN_MIC],
@@ -3507,6 +3548,8 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
3507 cfg->input_pins[AUTO_PIN_FRONT_LINE], 3548 cfg->input_pins[AUTO_PIN_FRONT_LINE],
3508 cfg->input_pins[AUTO_PIN_CD], 3549 cfg->input_pins[AUTO_PIN_CD],
3509 cfg->input_pins[AUTO_PIN_AUX]); 3550 cfg->input_pins[AUTO_PIN_AUX]);
3551 if (cfg->dig_out_pin)
3552 snd_printd(" dig-in=0x%x\n", cfg->dig_in_pin);
3510 3553
3511 return 0; 3554 return 0;
3512} 3555}
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index 1dd8716c387f..ec687b206c0a 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -26,8 +26,10 @@
26/* 26/*
27 * for mixer controls 27 * for mixer controls
28 */ 28 */
29#define HDA_COMPOSE_AMP_VAL_OFS(nid,chs,idx,dir,ofs) \
30 ((nid) | ((chs)<<16) | ((dir)<<18) | ((idx)<<19) | ((ofs)<<23))
29#define HDA_COMPOSE_AMP_VAL(nid,chs,idx,dir) \ 31#define HDA_COMPOSE_AMP_VAL(nid,chs,idx,dir) \
30 ((nid) | ((chs)<<16) | ((dir)<<18) | ((idx)<<19)) 32 HDA_COMPOSE_AMP_VAL_OFS(nid, chs, idx, dir, 0)
31/* mono volume with index (index=0,1,...) (channel=1,2) */ 33/* mono volume with index (index=0,1,...) (channel=1,2) */
32#define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ 34#define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \
33 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ 35 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \
@@ -355,6 +357,8 @@ struct auto_pin_cfg {
355 hda_nid_t dig_out_pin; 357 hda_nid_t dig_out_pin;
356 hda_nid_t dig_in_pin; 358 hda_nid_t dig_in_pin;
357 hda_nid_t mono_out_pin; 359 hda_nid_t mono_out_pin;
360 int dig_out_type; /* HDA_PCM_TYPE_XXX */
361 int dig_in_type; /* HDA_PCM_TYPE_XXX */
358}; 362};
359 363
360#define get_defcfg_connect(cfg) \ 364#define get_defcfg_connect(cfg) \
@@ -456,6 +460,7 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec,
456#define get_amp_channels(kc) (((kc)->private_value >> 16) & 0x3) 460#define get_amp_channels(kc) (((kc)->private_value >> 16) & 0x3)
457#define get_amp_direction(kc) (((kc)->private_value >> 18) & 0x1) 461#define get_amp_direction(kc) (((kc)->private_value >> 18) & 0x1)
458#define get_amp_index(kc) (((kc)->private_value >> 19) & 0xf) 462#define get_amp_index(kc) (((kc)->private_value >> 19) & 0xf)
463#define get_amp_offset(kc) (((kc)->private_value >> 23) & 0x3f)
459 464
460/* 465/*
461 * CEA Short Audio Descriptor data 466 * CEA Short Audio Descriptor data
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 5d249a547fbf..4cfa78c54398 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -269,6 +269,7 @@ struct alc_spec {
269 * dig_out_nid and hp_nid are optional 269 * dig_out_nid and hp_nid are optional
270 */ 270 */
271 hda_nid_t alt_dac_nid; 271 hda_nid_t alt_dac_nid;
272 int dig_out_type;
272 273
273 /* capture */ 274 /* capture */
274 unsigned int num_adc_nids; 275 unsigned int num_adc_nids;
@@ -305,6 +306,9 @@ struct alc_spec {
305 unsigned int jack_present: 1; 306 unsigned int jack_present: 1;
306 unsigned int master_sw: 1; 307 unsigned int master_sw: 1;
307 308
309 /* other flags */
310 unsigned int no_analog :1; /* digital I/O only */
311
308 /* for virtual master */ 312 /* for virtual master */
309 hda_nid_t vmaster_nid; 313 hda_nid_t vmaster_nid;
310#ifdef CONFIG_SND_HDA_POWER_SAVE 314#ifdef CONFIG_SND_HDA_POWER_SAVE
@@ -2018,11 +2022,13 @@ static int alc_build_controls(struct hda_codec *codec)
2018 spec->multiout.dig_out_nid); 2022 spec->multiout.dig_out_nid);
2019 if (err < 0) 2023 if (err < 0)
2020 return err; 2024 return err;
2021 err = snd_hda_create_spdif_share_sw(codec, 2025 if (!spec->no_analog) {
2022 &spec->multiout); 2026 err = snd_hda_create_spdif_share_sw(codec,
2023 if (err < 0) 2027 &spec->multiout);
2024 return err; 2028 if (err < 0)
2025 spec->multiout.share_spdif = 1; 2029 return err;
2030 spec->multiout.share_spdif = 1;
2031 }
2026 } 2032 }
2027 if (spec->dig_in_nid) { 2033 if (spec->dig_in_nid) {
2028 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid); 2034 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
@@ -2031,7 +2037,8 @@ static int alc_build_controls(struct hda_codec *codec)
2031 } 2037 }
2032 2038
2033 /* if we have no master control, let's create it */ 2039 /* if we have no master control, let's create it */
2034 if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) { 2040 if (!spec->no_analog &&
2041 !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
2035 unsigned int vmaster_tlv[4]; 2042 unsigned int vmaster_tlv[4];
2036 snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid, 2043 snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
2037 HDA_OUTPUT, vmaster_tlv); 2044 HDA_OUTPUT, vmaster_tlv);
@@ -2040,7 +2047,8 @@ static int alc_build_controls(struct hda_codec *codec)
2040 if (err < 0) 2047 if (err < 0)
2041 return err; 2048 return err;
2042 } 2049 }
2043 if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { 2050 if (!spec->no_analog &&
2051 !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
2044 err = snd_hda_add_vmaster(codec, "Master Playback Switch", 2052 err = snd_hda_add_vmaster(codec, "Master Playback Switch",
2045 NULL, alc_slave_sws); 2053 NULL, alc_slave_sws);
2046 if (err < 0) 2054 if (err < 0)
@@ -3059,6 +3067,9 @@ static int alc_build_pcms(struct hda_codec *codec)
3059 codec->num_pcms = 1; 3067 codec->num_pcms = 1;
3060 codec->pcm_info = info; 3068 codec->pcm_info = info;
3061 3069
3070 if (spec->no_analog)
3071 goto skip_analog;
3072
3062 info->name = spec->stream_name_analog; 3073 info->name = spec->stream_name_analog;
3063 if (spec->stream_analog_playback) { 3074 if (spec->stream_analog_playback) {
3064 if (snd_BUG_ON(!spec->multiout.dac_nids)) 3075 if (snd_BUG_ON(!spec->multiout.dac_nids))
@@ -3082,12 +3093,16 @@ static int alc_build_pcms(struct hda_codec *codec)
3082 } 3093 }
3083 } 3094 }
3084 3095
3096 skip_analog:
3085 /* SPDIF for stream index #1 */ 3097 /* SPDIF for stream index #1 */
3086 if (spec->multiout.dig_out_nid || spec->dig_in_nid) { 3098 if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
3087 codec->num_pcms = 2; 3099 codec->num_pcms = 2;
3088 info = spec->pcm_rec + 1; 3100 info = spec->pcm_rec + 1;
3089 info->name = spec->stream_name_digital; 3101 info->name = spec->stream_name_digital;
3090 info->pcm_type = HDA_PCM_TYPE_SPDIF; 3102 if (spec->dig_out_type)
3103 info->pcm_type = spec->dig_out_type;
3104 else
3105 info->pcm_type = HDA_PCM_TYPE_SPDIF;
3091 if (spec->multiout.dig_out_nid && 3106 if (spec->multiout.dig_out_nid &&
3092 spec->stream_digital_playback) { 3107 spec->stream_digital_playback) {
3093 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_digital_playback); 3108 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_digital_playback);
@@ -3102,6 +3117,9 @@ static int alc_build_pcms(struct hda_codec *codec)
3102 codec->spdif_status_reset = 1; 3117 codec->spdif_status_reset = 1;
3103 } 3118 }
3104 3119
3120 if (spec->no_analog)
3121 return 0;
3122
3105 /* If the use of more than one ADC is requested for the current 3123 /* If the use of more than one ADC is requested for the current
3106 * model, configure a second analog capture-only PCM. 3124 * model, configure a second analog capture-only PCM.
3107 */ 3125 */
@@ -10464,8 +10482,14 @@ static int alc262_parse_auto_config(struct hda_codec *codec)
10464 alc262_ignore); 10482 alc262_ignore);
10465 if (err < 0) 10483 if (err < 0)
10466 return err; 10484 return err;
10467 if (!spec->autocfg.line_outs) 10485 if (!spec->autocfg.line_outs) {
10486 if (spec->autocfg.dig_out_pin || spec->autocfg.dig_in_pin) {
10487 spec->multiout.max_channels = 2;
10488 spec->no_analog = 1;
10489 goto dig_only;
10490 }
10468 return 0; /* can't find valid BIOS pin config */ 10491 return 0; /* can't find valid BIOS pin config */
10492 }
10469 err = alc262_auto_create_multi_out_ctls(spec, &spec->autocfg); 10493 err = alc262_auto_create_multi_out_ctls(spec, &spec->autocfg);
10470 if (err < 0) 10494 if (err < 0)
10471 return err; 10495 return err;
@@ -10475,8 +10499,11 @@ static int alc262_parse_auto_config(struct hda_codec *codec)
10475 10499
10476 spec->multiout.max_channels = spec->multiout.num_dacs * 2; 10500 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
10477 10501
10478 if (spec->autocfg.dig_out_pin) 10502 dig_only:
10503 if (spec->autocfg.dig_out_pin) {
10479 spec->multiout.dig_out_nid = ALC262_DIGOUT_NID; 10504 spec->multiout.dig_out_nid = ALC262_DIGOUT_NID;
10505 spec->dig_out_type = spec->autocfg.dig_out_type;
10506 }
10480 if (spec->autocfg.dig_in_pin) 10507 if (spec->autocfg.dig_in_pin)
10481 spec->dig_in_nid = ALC262_DIGIN_NID; 10508 spec->dig_in_nid = ALC262_DIGIN_NID;
10482 10509
@@ -10871,7 +10898,7 @@ static int patch_alc262(struct hda_codec *codec)
10871 spec->capsrc_nids = alc262_capsrc_nids; 10898 spec->capsrc_nids = alc262_capsrc_nids;
10872 } 10899 }
10873 } 10900 }
10874 if (!spec->cap_mixer) 10901 if (!spec->cap_mixer && !spec->no_analog)
10875 set_capture_mixer(spec); 10902 set_capture_mixer(spec);
10876 10903
10877 spec->vmaster_nid = 0x0c; 10904 spec->vmaster_nid = 0x0c;
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 3dd4eee70b7c..212d8c09a67b 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -66,6 +66,7 @@ enum {
66 STAC_9205_DELL_M42, 66 STAC_9205_DELL_M42,
67 STAC_9205_DELL_M43, 67 STAC_9205_DELL_M43,
68 STAC_9205_DELL_M44, 68 STAC_9205_DELL_M44,
69 STAC_9205_EAPD,
69 STAC_9205_MODELS 70 STAC_9205_MODELS
70}; 71};
71 72
@@ -167,6 +168,7 @@ struct sigmatel_spec {
167 unsigned int alt_switch: 1; 168 unsigned int alt_switch: 1;
168 unsigned int hp_detect: 1; 169 unsigned int hp_detect: 1;
169 unsigned int spdif_mute: 1; 170 unsigned int spdif_mute: 1;
171 unsigned int check_volume_offset:1;
170 172
171 /* gpio lines */ 173 /* gpio lines */
172 unsigned int eapd_mask; 174 unsigned int eapd_mask;
@@ -203,6 +205,8 @@ struct sigmatel_spec {
203 hda_nid_t hp_dacs[5]; 205 hda_nid_t hp_dacs[5];
204 hda_nid_t speaker_dacs[5]; 206 hda_nid_t speaker_dacs[5];
205 207
208 int volume_offset;
209
206 /* capture */ 210 /* capture */
207 hda_nid_t *adc_nids; 211 hda_nid_t *adc_nids;
208 unsigned int num_adcs; 212 unsigned int num_adcs;
@@ -1294,6 +1298,8 @@ static int stac92xx_build_controls(struct hda_codec *codec)
1294 unsigned int vmaster_tlv[4]; 1298 unsigned int vmaster_tlv[4];
1295 snd_hda_set_vmaster_tlv(codec, spec->multiout.dac_nids[0], 1299 snd_hda_set_vmaster_tlv(codec, spec->multiout.dac_nids[0],
1296 HDA_OUTPUT, vmaster_tlv); 1300 HDA_OUTPUT, vmaster_tlv);
1301 /* correct volume offset */
1302 vmaster_tlv[2] += vmaster_tlv[3] * spec->volume_offset;
1297 err = snd_hda_add_vmaster(codec, "Master Playback Volume", 1303 err = snd_hda_add_vmaster(codec, "Master Playback Volume",
1298 vmaster_tlv, slave_vols); 1304 vmaster_tlv, slave_vols);
1299 if (err < 0) 1305 if (err < 0)
@@ -2238,6 +2244,7 @@ static unsigned int *stac9205_brd_tbl[STAC_9205_MODELS] = {
2238 [STAC_9205_DELL_M42] = dell_9205_m42_pin_configs, 2244 [STAC_9205_DELL_M42] = dell_9205_m42_pin_configs,
2239 [STAC_9205_DELL_M43] = dell_9205_m43_pin_configs, 2245 [STAC_9205_DELL_M43] = dell_9205_m43_pin_configs,
2240 [STAC_9205_DELL_M44] = dell_9205_m44_pin_configs, 2246 [STAC_9205_DELL_M44] = dell_9205_m44_pin_configs,
2247 [STAC_9205_EAPD] = NULL,
2241}; 2248};
2242 2249
2243static const char *stac9205_models[STAC_9205_MODELS] = { 2250static const char *stac9205_models[STAC_9205_MODELS] = {
@@ -2245,12 +2252,14 @@ static const char *stac9205_models[STAC_9205_MODELS] = {
2245 [STAC_9205_DELL_M42] = "dell-m42", 2252 [STAC_9205_DELL_M42] = "dell-m42",
2246 [STAC_9205_DELL_M43] = "dell-m43", 2253 [STAC_9205_DELL_M43] = "dell-m43",
2247 [STAC_9205_DELL_M44] = "dell-m44", 2254 [STAC_9205_DELL_M44] = "dell-m44",
2255 [STAC_9205_EAPD] = "eapd",
2248}; 2256};
2249 2257
2250static struct snd_pci_quirk stac9205_cfg_tbl[] = { 2258static struct snd_pci_quirk stac9205_cfg_tbl[] = {
2251 /* SigmaTel reference board */ 2259 /* SigmaTel reference board */
2252 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, 2260 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
2253 "DFI LanParty", STAC_9205_REF), 2261 "DFI LanParty", STAC_9205_REF),
2262 /* Dell */
2254 SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f1, 2263 SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f1,
2255 "unknown Dell", STAC_9205_DELL_M42), 2264 "unknown Dell", STAC_9205_DELL_M42),
2256 SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f2, 2265 SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f2,
@@ -2281,6 +2290,8 @@ static struct snd_pci_quirk stac9205_cfg_tbl[] = {
2281 "Dell Inspiron", STAC_9205_DELL_M44), 2290 "Dell Inspiron", STAC_9205_DELL_M44),
2282 SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0228, 2291 SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0228,
2283 "Dell Vostro 1500", STAC_9205_DELL_M42), 2292 "Dell Vostro 1500", STAC_9205_DELL_M42),
2293 /* Gateway */
2294 SND_PCI_QUIRK(0x107b, 0x0565, "Gateway T1616", STAC_9205_EAPD),
2284 {} /* terminator */ 2295 {} /* terminator */
2285}; 2296};
2286 2297
@@ -2554,7 +2565,7 @@ static int stac92xx_build_pcms(struct hda_codec *codec)
2554 codec->num_pcms++; 2565 codec->num_pcms++;
2555 info++; 2566 info++;
2556 info->name = "STAC92xx Digital"; 2567 info->name = "STAC92xx Digital";
2557 info->pcm_type = HDA_PCM_TYPE_SPDIF; 2568 info->pcm_type = spec->autocfg.dig_out_type;
2558 if (spec->multiout.dig_out_nid) { 2569 if (spec->multiout.dig_out_nid) {
2559 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_digital_playback; 2570 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_digital_playback;
2560 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid; 2571 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
@@ -2981,14 +2992,34 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec)
2981} 2992}
2982 2993
2983/* create volume control/switch for the given prefx type */ 2994/* create volume control/switch for the given prefx type */
2984static int create_controls(struct sigmatel_spec *spec, const char *pfx, hda_nid_t nid, int chs) 2995static int create_controls(struct hda_codec *codec, const char *pfx,
2996 hda_nid_t nid, int chs)
2985{ 2997{
2998 struct sigmatel_spec *spec = codec->spec;
2986 char name[32]; 2999 char name[32];
2987 int err; 3000 int err;
2988 3001
3002 if (!spec->check_volume_offset) {
3003 unsigned int caps, step, nums, db_scale;
3004 caps = query_amp_caps(codec, nid, HDA_OUTPUT);
3005 step = (caps & AC_AMPCAP_STEP_SIZE) >>
3006 AC_AMPCAP_STEP_SIZE_SHIFT;
3007 step = (step + 1) * 25; /* in .01dB unit */
3008 nums = (caps & AC_AMPCAP_NUM_STEPS) >>
3009 AC_AMPCAP_NUM_STEPS_SHIFT;
3010 db_scale = nums * step;
3011 /* if dB scale is over -64dB, and finer enough,
3012 * let's reduce it to half
3013 */
3014 if (db_scale > 6400 && nums >= 0x1f)
3015 spec->volume_offset = nums / 2;
3016 spec->check_volume_offset = 1;
3017 }
3018
2989 sprintf(name, "%s Playback Volume", pfx); 3019 sprintf(name, "%s Playback Volume", pfx);
2990 err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, name, 3020 err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, name,
2991 HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT)); 3021 HDA_COMPOSE_AMP_VAL_OFS(nid, chs, 0, HDA_OUTPUT,
3022 spec->volume_offset));
2992 if (err < 0) 3023 if (err < 0)
2993 return err; 3024 return err;
2994 sprintf(name, "%s Playback Switch", pfx); 3025 sprintf(name, "%s Playback Switch", pfx);
@@ -3054,10 +3085,10 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
3054 nid = spec->multiout.dac_nids[i]; 3085 nid = spec->multiout.dac_nids[i];
3055 if (i == 2) { 3086 if (i == 2) {
3056 /* Center/LFE */ 3087 /* Center/LFE */
3057 err = create_controls(spec, "Center", nid, 1); 3088 err = create_controls(codec, "Center", nid, 1);
3058 if (err < 0) 3089 if (err < 0)
3059 return err; 3090 return err;
3060 err = create_controls(spec, "LFE", nid, 2); 3091 err = create_controls(codec, "LFE", nid, 2);
3061 if (err < 0) 3092 if (err < 0)
3062 return err; 3093 return err;
3063 3094
@@ -3085,7 +3116,7 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
3085 break; 3116 break;
3086 } 3117 }
3087 } 3118 }
3088 err = create_controls(spec, name, nid, 3); 3119 err = create_controls(codec, name, nid, 3);
3089 if (err < 0) 3120 if (err < 0)
3090 return err; 3121 return err;
3091 } 3122 }
@@ -3140,7 +3171,7 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec,
3140 nid = spec->hp_dacs[i]; 3171 nid = spec->hp_dacs[i];
3141 if (!nid) 3172 if (!nid)
3142 continue; 3173 continue;
3143 err = create_controls(spec, pfxs[nums++], nid, 3); 3174 err = create_controls(codec, pfxs[nums++], nid, 3);
3144 if (err < 0) 3175 if (err < 0)
3145 return err; 3176 return err;
3146 } 3177 }
@@ -3154,7 +3185,7 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec,
3154 nid = spec->speaker_dacs[i]; 3185 nid = spec->speaker_dacs[i];
3155 if (!nid) 3186 if (!nid)
3156 continue; 3187 continue;
3157 err = create_controls(spec, pfxs[nums++], nid, 3); 3188 err = create_controls(codec, pfxs[nums++], nid, 3);
3158 if (err < 0) 3189 if (err < 0)
3159 return err; 3190 return err;
3160 } 3191 }
@@ -3730,7 +3761,7 @@ static int stac9200_auto_create_lfe_ctls(struct hda_codec *codec,
3730 } 3761 }
3731 3762
3732 if (lfe_pin) { 3763 if (lfe_pin) {
3733 err = create_controls(spec, "LFE", lfe_pin, 1); 3764 err = create_controls(codec, "LFE", lfe_pin, 1);
3734 if (err < 0) 3765 if (err < 0)
3735 return err; 3766 return err;
3736 } 3767 }
@@ -4106,7 +4137,9 @@ static void stac92xx_free(struct hda_codec *codec)
4106static void stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid, 4137static void stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid,
4107 unsigned int flag) 4138 unsigned int flag)
4108{ 4139{
4109 unsigned int pin_ctl = snd_hda_codec_read(codec, nid, 4140 unsigned int old_ctl, pin_ctl;
4141
4142 pin_ctl = snd_hda_codec_read(codec, nid,
4110 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00); 4143 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00);
4111 4144
4112 if (pin_ctl & AC_PINCTL_IN_EN) { 4145 if (pin_ctl & AC_PINCTL_IN_EN) {
@@ -4120,14 +4153,17 @@ static void stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid,
4120 return; 4153 return;
4121 } 4154 }
4122 4155
4156 old_ctl = pin_ctl;
4123 /* if setting pin direction bits, clear the current 4157 /* if setting pin direction bits, clear the current
4124 direction bits first */ 4158 direction bits first */
4125 if (flag & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN)) 4159 if (flag & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN))
4126 pin_ctl &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN); 4160 pin_ctl &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN);
4127 4161
4128 snd_hda_codec_write_cache(codec, nid, 0, 4162 pin_ctl |= flag;
4129 AC_VERB_SET_PIN_WIDGET_CONTROL, 4163 if (old_ctl != pin_ctl)
4130 pin_ctl | flag); 4164 snd_hda_codec_write_cache(codec, nid, 0,
4165 AC_VERB_SET_PIN_WIDGET_CONTROL,
4166 pin_ctl);
4131} 4167}
4132 4168
4133static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid, 4169static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid,
@@ -4135,9 +4171,10 @@ static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid,
4135{ 4171{
4136 unsigned int pin_ctl = snd_hda_codec_read(codec, nid, 4172 unsigned int pin_ctl = snd_hda_codec_read(codec, nid,
4137 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00); 4173 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00);
4138 snd_hda_codec_write_cache(codec, nid, 0, 4174 if (pin_ctl & flag)
4139 AC_VERB_SET_PIN_WIDGET_CONTROL, 4175 snd_hda_codec_write_cache(codec, nid, 0,
4140 pin_ctl & ~flag); 4176 AC_VERB_SET_PIN_WIDGET_CONTROL,
4177 pin_ctl & ~flag);
4141} 4178}
4142 4179
4143static int get_pin_presence(struct hda_codec *codec, hda_nid_t nid) 4180static int get_pin_presence(struct hda_codec *codec, hda_nid_t nid)
@@ -5294,7 +5331,9 @@ static int patch_stac9205(struct hda_codec *codec)
5294 5331
5295 spec->aloopback_mask = 0x40; 5332 spec->aloopback_mask = 0x40;
5296 spec->aloopback_shift = 0; 5333 spec->aloopback_shift = 0;
5297 spec->eapd_switch = 1; 5334 /* Turn on/off EAPD per HP plugging */
5335 if (spec->board_config != STAC_9205_EAPD)
5336 spec->eapd_switch = 1;
5298 spec->multiout.dac_nids = spec->dac_nids; 5337 spec->multiout.dac_nids = spec->dac_nids;
5299 5338
5300 switch (spec->board_config){ 5339 switch (spec->board_config){
@@ -5358,223 +5397,65 @@ static int patch_stac9205(struct hda_codec *codec)
5358 * STAC9872 hack 5397 * STAC9872 hack
5359 */ 5398 */
5360 5399
5361/* static config for Sony VAIO FE550G and Sony VAIO AR */ 5400static struct hda_verb stac9872_core_init[] = {
5362static hda_nid_t vaio_dacs[] = { 0x2 };
5363#define VAIO_HP_DAC 0x5
5364static hda_nid_t vaio_adcs[] = { 0x8 /*,0x6*/ };
5365static hda_nid_t vaio_mux_nids[] = { 0x15 };
5366
5367static struct hda_input_mux vaio_mux = {
5368 .num_items = 3,
5369 .items = {
5370 /* { "HP", 0x0 }, */
5371 { "Mic Jack", 0x1 },
5372 { "Internal Mic", 0x2 },
5373 { "PCM", 0x3 },
5374 }
5375};
5376
5377static struct hda_verb vaio_init[] = {
5378 {0x0a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP <- 0x2 */
5379 {0x0a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | STAC_HP_EVENT},
5380 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Speaker <- 0x5 */
5381 {0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? (<- 0x2) */
5382 {0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD */
5383 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? */
5384 {0x15, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mic-sel: 0a,0d,14,02 */ 5401 {0x15, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mic-sel: 0a,0d,14,02 */
5385 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* HP */
5386 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Speaker */
5387 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* capture sw/vol -> 0x8 */
5388 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, /* CD-in -> 0x6 */
5389 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Mic-in -> 0x9 */ 5402 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Mic-in -> 0x9 */
5390 {} 5403 {}
5391}; 5404};
5392 5405
5393static struct hda_verb vaio_ar_init[] = { 5406static struct snd_kcontrol_new stac9872_mixer[] = {
5394 {0x0a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP <- 0x2 */
5395 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Speaker <- 0x5 */
5396 {0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? (<- 0x2) */
5397 {0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD */
5398/* {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },*/ /* Optical Out */
5399 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? */
5400 {0x15, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mic-sel: 0a,0d,14,02 */
5401 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* HP */
5402 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Speaker */
5403/* {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},*/ /* Optical Out */
5404 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* capture sw/vol -> 0x8 */
5405 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, /* CD-in -> 0x6 */
5406 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Mic-in -> 0x9 */
5407 {}
5408};
5409
5410static struct snd_kcontrol_new vaio_mixer[] = {
5411 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x02, 0, HDA_OUTPUT),
5412 HDA_CODEC_MUTE("Headphone Playback Switch", 0x02, 0, HDA_OUTPUT),
5413 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x05, 0, HDA_OUTPUT),
5414 HDA_CODEC_MUTE("Speaker Playback Switch", 0x05, 0, HDA_OUTPUT),
5415 /* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */
5416 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT), 5407 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT),
5417 HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT), 5408 HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT),
5418 { 5409 STAC_INPUT_SOURCE(1),
5419 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 5410 { } /* end */
5420 .name = "Capture Source",
5421 .count = 1,
5422 .info = stac92xx_mux_enum_info,
5423 .get = stac92xx_mux_enum_get,
5424 .put = stac92xx_mux_enum_put,
5425 },
5426 {}
5427};
5428
5429static struct snd_kcontrol_new vaio_ar_mixer[] = {
5430 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x02, 0, HDA_OUTPUT),
5431 HDA_CODEC_MUTE("Headphone Playback Switch", 0x02, 0, HDA_OUTPUT),
5432 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x05, 0, HDA_OUTPUT),
5433 HDA_CODEC_MUTE("Speaker Playback Switch", 0x05, 0, HDA_OUTPUT),
5434 /* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */
5435 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT),
5436 HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT),
5437 /*HDA_CODEC_MUTE("Optical Out Switch", 0x10, 0, HDA_OUTPUT),
5438 HDA_CODEC_VOLUME("Optical Out Volume", 0x10, 0, HDA_OUTPUT),*/
5439 {
5440 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5441 .name = "Capture Source",
5442 .count = 1,
5443 .info = stac92xx_mux_enum_info,
5444 .get = stac92xx_mux_enum_get,
5445 .put = stac92xx_mux_enum_put,
5446 },
5447 {}
5448};
5449
5450static struct hda_codec_ops stac9872_patch_ops = {
5451 .build_controls = stac92xx_build_controls,
5452 .build_pcms = stac92xx_build_pcms,
5453 .init = stac92xx_init,
5454 .free = stac92xx_free,
5455#ifdef SND_HDA_NEEDS_RESUME
5456 .resume = stac92xx_resume,
5457#endif
5458};
5459
5460static int stac9872_vaio_init(struct hda_codec *codec)
5461{
5462 int err;
5463
5464 err = stac92xx_init(codec);
5465 if (err < 0)
5466 return err;
5467 if (codec->patch_ops.unsol_event)
5468 codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26);
5469 return 0;
5470}
5471
5472static void stac9872_vaio_hp_detect(struct hda_codec *codec, unsigned int res)
5473{
5474 if (get_pin_presence(codec, 0x0a)) {
5475 stac92xx_reset_pinctl(codec, 0x0f, AC_PINCTL_OUT_EN);
5476 stac92xx_set_pinctl(codec, 0x0a, AC_PINCTL_OUT_EN);
5477 } else {
5478 stac92xx_reset_pinctl(codec, 0x0a, AC_PINCTL_OUT_EN);
5479 stac92xx_set_pinctl(codec, 0x0f, AC_PINCTL_OUT_EN);
5480 }
5481}
5482
5483static void stac9872_vaio_unsol_event(struct hda_codec *codec, unsigned int res)
5484{
5485 switch (res >> 26) {
5486 case STAC_HP_EVENT:
5487 stac9872_vaio_hp_detect(codec, res);
5488 break;
5489 }
5490}
5491
5492static struct hda_codec_ops stac9872_vaio_patch_ops = {
5493 .build_controls = stac92xx_build_controls,
5494 .build_pcms = stac92xx_build_pcms,
5495 .init = stac9872_vaio_init,
5496 .free = stac92xx_free,
5497 .unsol_event = stac9872_vaio_unsol_event,
5498#ifdef CONFIG_PM
5499 .resume = stac92xx_resume,
5500#endif
5501}; 5411};
5502 5412
5503enum { /* FE and SZ series. id=0x83847661 and subsys=0x104D0700 or 104D1000. */ 5413static hda_nid_t stac9872_pin_nids[] = {
5504 CXD9872RD_VAIO, 5414 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
5505 /* Unknown. id=0x83847662 and subsys=0x104D1200 or 104D1000. */ 5415 0x11, 0x13, 0x14,
5506 STAC9872AK_VAIO,
5507 /* Unknown. id=0x83847661 and subsys=0x104D1200. */
5508 STAC9872K_VAIO,
5509 /* AR Series. id=0x83847664 and subsys=104D1300 */
5510 CXD9872AKD_VAIO,
5511 STAC_9872_MODELS,
5512}; 5416};
5513 5417
5514static const char *stac9872_models[STAC_9872_MODELS] = { 5418static hda_nid_t stac9872_adc_nids[] = {
5515 [CXD9872RD_VAIO] = "vaio", 5419 0x8 /*,0x6*/
5516 [CXD9872AKD_VAIO] = "vaio-ar",
5517}; 5420};
5518 5421
5519static struct snd_pci_quirk stac9872_cfg_tbl[] = { 5422static hda_nid_t stac9872_mux_nids[] = {
5520 SND_PCI_QUIRK(0x104d, 0x81e6, "Sony VAIO F/S", CXD9872RD_VAIO), 5423 0x15
5521 SND_PCI_QUIRK(0x104d, 0x81ef, "Sony VAIO F/S", CXD9872RD_VAIO),
5522 SND_PCI_QUIRK(0x104d, 0x81fd, "Sony VAIO AR", CXD9872AKD_VAIO),
5523 SND_PCI_QUIRK(0x104d, 0x8205, "Sony VAIO AR", CXD9872AKD_VAIO),
5524 {}
5525}; 5424};
5526 5425
5527static int patch_stac9872(struct hda_codec *codec) 5426static int patch_stac9872(struct hda_codec *codec)
5528{ 5427{
5529 struct sigmatel_spec *spec; 5428 struct sigmatel_spec *spec;
5530 int board_config; 5429 int err;
5531 5430
5532 board_config = snd_hda_check_board_config(codec, STAC_9872_MODELS,
5533 stac9872_models,
5534 stac9872_cfg_tbl);
5535 if (board_config < 0)
5536 /* unknown config, let generic-parser do its job... */
5537 return snd_hda_parse_generic_codec(codec);
5538
5539 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 5431 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
5540 if (spec == NULL) 5432 if (spec == NULL)
5541 return -ENOMEM; 5433 return -ENOMEM;
5542
5543 codec->spec = spec; 5434 codec->spec = spec;
5544 switch (board_config) {
5545 case CXD9872RD_VAIO:
5546 case STAC9872AK_VAIO:
5547 case STAC9872K_VAIO:
5548 spec->mixer = vaio_mixer;
5549 spec->init = vaio_init;
5550 spec->multiout.max_channels = 2;
5551 spec->multiout.num_dacs = ARRAY_SIZE(vaio_dacs);
5552 spec->multiout.dac_nids = vaio_dacs;
5553 spec->multiout.hp_nid = VAIO_HP_DAC;
5554 spec->num_adcs = ARRAY_SIZE(vaio_adcs);
5555 spec->adc_nids = vaio_adcs;
5556 spec->num_pwrs = 0;
5557 spec->input_mux = &vaio_mux;
5558 spec->mux_nids = vaio_mux_nids;
5559 codec->patch_ops = stac9872_vaio_patch_ops;
5560 break;
5561
5562 case CXD9872AKD_VAIO:
5563 spec->mixer = vaio_ar_mixer;
5564 spec->init = vaio_ar_init;
5565 spec->multiout.max_channels = 2;
5566 spec->multiout.num_dacs = ARRAY_SIZE(vaio_dacs);
5567 spec->multiout.dac_nids = vaio_dacs;
5568 spec->multiout.hp_nid = VAIO_HP_DAC;
5569 spec->num_adcs = ARRAY_SIZE(vaio_adcs);
5570 spec->num_pwrs = 0;
5571 spec->adc_nids = vaio_adcs;
5572 spec->input_mux = &vaio_mux;
5573 spec->mux_nids = vaio_mux_nids;
5574 codec->patch_ops = stac9872_patch_ops;
5575 break;
5576 }
5577 5435
5436#if 0 /* no model right now */
5437 spec->board_config = snd_hda_check_board_config(codec, STAC_9872_MODELS,
5438 stac9872_models,
5439 stac9872_cfg_tbl);
5440#endif
5441
5442 spec->num_pins = ARRAY_SIZE(stac9872_pin_nids);
5443 spec->pin_nids = stac9872_pin_nids;
5444 spec->multiout.dac_nids = spec->dac_nids;
5445 spec->num_adcs = ARRAY_SIZE(stac9872_adc_nids);
5446 spec->adc_nids = stac9872_adc_nids;
5447 spec->num_muxes = ARRAY_SIZE(stac9872_mux_nids);
5448 spec->mux_nids = stac9872_mux_nids;
5449 spec->mixer = stac9872_mixer;
5450 spec->init = stac9872_core_init;
5451
5452 err = stac92xx_parse_auto_config(codec, 0x10, 0x12);
5453 if (err < 0) {
5454 stac92xx_free(codec);
5455 return -EINVAL;
5456 }
5457 spec->input_mux = &spec->private_imux;
5458 codec->patch_ops = stac92xx_patch_ops;
5578 return 0; 5459 return 0;
5579} 5460}
5580 5461