diff options
-rw-r--r-- | Documentation/sound/alsa/HD-Audio-Models.txt | 4 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.c | 61 | ||||
-rw-r--r-- | sound/pci/hda/hda_local.h | 7 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 49 | ||||
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 301 |
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 | ||
289 | STAC9220/9221 | 290 | STAC9220/9221 |
290 | ============= | 291 | ============= |
@@ -353,5 +354,4 @@ STAC92HD83* | |||
353 | 354 | ||
354 | STAC9872 | 355 | STAC9872 |
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 | } |
1139 | EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info); | 1142 | EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info); |
1140 | 1143 | ||
1144 | |||
1145 | static inline unsigned int | ||
1146 | read_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 | |||
1159 | static inline int | ||
1160 | update_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 | |||
1141 | int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol, | 1170 | int 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 | } |
1159 | EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_get); | 1187 | EXPORT_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 | ||
2243 | static const char *stac9205_models[STAC_9205_MODELS] = { | 2250 | static 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 | ||
2250 | static struct snd_pci_quirk stac9205_cfg_tbl[] = { | 2258 | static 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 */ |
2984 | static int create_controls(struct sigmatel_spec *spec, const char *pfx, hda_nid_t nid, int chs) | 2995 | static 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) | |||
4106 | static void stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid, | 4137 | static 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 | ||
4133 | static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid, | 4169 | static 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 | ||
4143 | static int get_pin_presence(struct hda_codec *codec, hda_nid_t nid) | 4180 | static 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 */ | 5400 | static struct hda_verb stac9872_core_init[] = { |
5362 | static hda_nid_t vaio_dacs[] = { 0x2 }; | ||
5363 | #define VAIO_HP_DAC 0x5 | ||
5364 | static hda_nid_t vaio_adcs[] = { 0x8 /*,0x6*/ }; | ||
5365 | static hda_nid_t vaio_mux_nids[] = { 0x15 }; | ||
5366 | |||
5367 | static 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 | |||
5377 | static 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 | ||
5393 | static struct hda_verb vaio_ar_init[] = { | 5406 | static 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 | |||
5410 | static 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 | |||
5429 | static 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 | |||
5450 | static 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 | |||
5460 | static 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 | |||
5472 | static 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 | |||
5483 | static 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 | |||
5492 | static 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 | ||
5503 | enum { /* FE and SZ series. id=0x83847661 and subsys=0x104D0700 or 104D1000. */ | 5413 | static 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 | ||
5514 | static const char *stac9872_models[STAC_9872_MODELS] = { | 5418 | static hda_nid_t stac9872_adc_nids[] = { |
5515 | [CXD9872RD_VAIO] = "vaio", | 5419 | 0x8 /*,0x6*/ |
5516 | [CXD9872AKD_VAIO] = "vaio-ar", | ||
5517 | }; | 5420 | }; |
5518 | 5421 | ||
5519 | static struct snd_pci_quirk stac9872_cfg_tbl[] = { | 5422 | static 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 | ||
5527 | static int patch_stac9872(struct hda_codec *codec) | 5426 | static 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 | ||