diff options
author | Takashi Iwai <tiwai@suse.de> | 2005-04-14 07:35:51 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2005-05-29 04:00:58 -0400 |
commit | 4a3fdf3dba80f332e6233e72bdbccdc6031fc92e (patch) | |
tree | 8b87c05579d45f1c35b4bb25ac51ca931b7bb6b2 /sound/pci/hda/patch_analog.c | |
parent | 2f2f4251c9b123b2ab04da9e78ab6158535c2e38 (diff) |
[ALSA] Add AD1981HD and AD1983 support
HDA Codec driver
Added the support of AD1981HD and AD1983 codecs.
Including the fix for AD1986A.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/patch_analog.c')
-rw-r--r-- | sound/pci/hda/patch_analog.c | 691 |
1 files changed, 522 insertions, 169 deletions
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 75d23849f71..caa48699344 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * HD audio interface patch for AD1986A | 2 | * HD audio interface patch for AD1981HD, AD1983, AD1986A |
3 | * | 3 | * |
4 | * Copyright (c) 2005 Takashi Iwai <tiwai@suse.de> | 4 | * Copyright (c) 2005 Takashi Iwai <tiwai@suse.de> |
5 | * | 5 | * |
@@ -27,13 +27,239 @@ | |||
27 | #include "hda_codec.h" | 27 | #include "hda_codec.h" |
28 | #include "hda_local.h" | 28 | #include "hda_local.h" |
29 | 29 | ||
30 | struct ad1986a_spec { | 30 | struct ad198x_spec { |
31 | struct semaphore amp_mutex; /* PCM volume/mute control mutex */ | 31 | struct semaphore amp_mutex; /* PCM volume/mute control mutex */ |
32 | struct hda_multi_out multiout; /* playback */ | 32 | struct hda_multi_out multiout; /* playback */ |
33 | hda_nid_t adc_nid; | ||
34 | const struct hda_input_mux *input_mux; | ||
33 | unsigned int cur_mux; /* capture source */ | 35 | unsigned int cur_mux; /* capture source */ |
36 | unsigned int spdif_route; | ||
37 | snd_kcontrol_new_t *mixers; | ||
38 | const struct hda_verb *init_verbs; | ||
34 | struct hda_pcm pcm_rec[2]; /* PCM information */ | 39 | struct hda_pcm pcm_rec[2]; /* PCM information */ |
35 | }; | 40 | }; |
36 | 41 | ||
42 | /* | ||
43 | * input MUX handling (common part) | ||
44 | */ | ||
45 | static int ad198x_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) | ||
46 | { | ||
47 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
48 | struct ad198x_spec *spec = codec->spec; | ||
49 | |||
50 | return snd_hda_input_mux_info(spec->input_mux, uinfo); | ||
51 | } | ||
52 | |||
53 | static int ad198x_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
54 | { | ||
55 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
56 | struct ad198x_spec *spec = codec->spec; | ||
57 | |||
58 | ucontrol->value.enumerated.item[0] = spec->cur_mux; | ||
59 | return 0; | ||
60 | } | ||
61 | |||
62 | static int ad198x_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
63 | { | ||
64 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
65 | struct ad198x_spec *spec = codec->spec; | ||
66 | |||
67 | return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol, | ||
68 | spec->adc_nid, &spec->cur_mux); | ||
69 | } | ||
70 | |||
71 | /* | ||
72 | * initialization (common callbacks) | ||
73 | */ | ||
74 | static int ad198x_init(struct hda_codec *codec) | ||
75 | { | ||
76 | struct ad198x_spec *spec = codec->spec; | ||
77 | snd_hda_sequence_write(codec, spec->init_verbs); | ||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | static int ad198x_build_controls(struct hda_codec *codec) | ||
82 | { | ||
83 | struct ad198x_spec *spec = codec->spec; | ||
84 | int err; | ||
85 | |||
86 | err = snd_hda_add_new_ctls(codec, spec->mixers); | ||
87 | if (err < 0) | ||
88 | return err; | ||
89 | if (spec->multiout.dig_out_nid) | ||
90 | err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid); | ||
91 | if (err < 0) | ||
92 | return err; | ||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | /* | ||
97 | * Analog playback callbacks | ||
98 | */ | ||
99 | static int ad198x_playback_pcm_open(struct hda_pcm_stream *hinfo, | ||
100 | struct hda_codec *codec, | ||
101 | snd_pcm_substream_t *substream) | ||
102 | { | ||
103 | struct ad198x_spec *spec = codec->spec; | ||
104 | return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream); | ||
105 | } | ||
106 | |||
107 | static int ad198x_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
108 | struct hda_codec *codec, | ||
109 | unsigned int stream_tag, | ||
110 | unsigned int format, | ||
111 | snd_pcm_substream_t *substream) | ||
112 | { | ||
113 | struct ad198x_spec *spec = codec->spec; | ||
114 | return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag, | ||
115 | format, substream); | ||
116 | } | ||
117 | |||
118 | static int ad198x_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, | ||
119 | struct hda_codec *codec, | ||
120 | snd_pcm_substream_t *substream) | ||
121 | { | ||
122 | struct ad198x_spec *spec = codec->spec; | ||
123 | return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout); | ||
124 | } | ||
125 | |||
126 | /* | ||
127 | * Digital out | ||
128 | */ | ||
129 | static int ad198x_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, | ||
130 | struct hda_codec *codec, | ||
131 | snd_pcm_substream_t *substream) | ||
132 | { | ||
133 | struct ad198x_spec *spec = codec->spec; | ||
134 | return snd_hda_multi_out_dig_open(codec, &spec->multiout); | ||
135 | } | ||
136 | |||
137 | static int ad198x_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, | ||
138 | struct hda_codec *codec, | ||
139 | snd_pcm_substream_t *substream) | ||
140 | { | ||
141 | struct ad198x_spec *spec = codec->spec; | ||
142 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | ||
143 | } | ||
144 | |||
145 | /* | ||
146 | * Analog capture | ||
147 | */ | ||
148 | static int ad198x_capture_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
149 | struct hda_codec *codec, | ||
150 | unsigned int stream_tag, | ||
151 | unsigned int format, | ||
152 | snd_pcm_substream_t *substream) | ||
153 | { | ||
154 | struct ad198x_spec *spec = codec->spec; | ||
155 | snd_hda_codec_setup_stream(codec, spec->adc_nid, stream_tag, 0, format); | ||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | static int ad198x_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, | ||
160 | struct hda_codec *codec, | ||
161 | snd_pcm_substream_t *substream) | ||
162 | { | ||
163 | struct ad198x_spec *spec = codec->spec; | ||
164 | snd_hda_codec_setup_stream(codec, spec->adc_nid, 0, 0, 0); | ||
165 | return 0; | ||
166 | } | ||
167 | |||
168 | |||
169 | /* | ||
170 | */ | ||
171 | static struct hda_pcm_stream ad198x_pcm_analog_playback = { | ||
172 | .substreams = 1, | ||
173 | .channels_min = 2, | ||
174 | .channels_max = 6, | ||
175 | .nid = 0, /* fill later */ | ||
176 | .ops = { | ||
177 | .open = ad198x_playback_pcm_open, | ||
178 | .prepare = ad198x_playback_pcm_prepare, | ||
179 | .cleanup = ad198x_playback_pcm_cleanup | ||
180 | }, | ||
181 | }; | ||
182 | |||
183 | static struct hda_pcm_stream ad198x_pcm_analog_capture = { | ||
184 | .substreams = 2, | ||
185 | .channels_min = 2, | ||
186 | .channels_max = 2, | ||
187 | .nid = 0, /* fill later */ | ||
188 | .ops = { | ||
189 | .prepare = ad198x_capture_pcm_prepare, | ||
190 | .cleanup = ad198x_capture_pcm_cleanup | ||
191 | }, | ||
192 | }; | ||
193 | |||
194 | static struct hda_pcm_stream ad198x_pcm_digital_playback = { | ||
195 | .substreams = 1, | ||
196 | .channels_min = 2, | ||
197 | .channels_max = 2, | ||
198 | .nid = 0, /* fill later */ | ||
199 | .ops = { | ||
200 | .open = ad198x_dig_playback_pcm_open, | ||
201 | .close = ad198x_dig_playback_pcm_close | ||
202 | }, | ||
203 | }; | ||
204 | |||
205 | static int ad198x_build_pcms(struct hda_codec *codec) | ||
206 | { | ||
207 | struct ad198x_spec *spec = codec->spec; | ||
208 | struct hda_pcm *info = spec->pcm_rec; | ||
209 | |||
210 | codec->num_pcms = 1; | ||
211 | codec->pcm_info = info; | ||
212 | |||
213 | info->name = "AD198x Analog"; | ||
214 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_analog_playback; | ||
215 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->multiout.max_channels; | ||
216 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0]; | ||
217 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_analog_capture; | ||
218 | info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nid; | ||
219 | |||
220 | if (spec->multiout.dig_out_nid) { | ||
221 | info++; | ||
222 | codec->num_pcms++; | ||
223 | info->name = "AD198x Digital"; | ||
224 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback; | ||
225 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid; | ||
226 | } | ||
227 | |||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | static void ad198x_free(struct hda_codec *codec) | ||
232 | { | ||
233 | kfree(codec->spec); | ||
234 | } | ||
235 | |||
236 | #ifdef CONFIG_PM | ||
237 | static int ad198x_resume(struct hda_codec *codec) | ||
238 | { | ||
239 | struct ad198x_spec *spec = codec->spec; | ||
240 | |||
241 | ad198x_init(codec); | ||
242 | snd_hda_resume_ctls(codec, spec->mixers); | ||
243 | snd_hda_resume_spdif_out(codec); | ||
244 | return 0; | ||
245 | } | ||
246 | #endif | ||
247 | |||
248 | static struct hda_codec_ops ad198x_patch_ops = { | ||
249 | .build_controls = ad198x_build_controls, | ||
250 | .build_pcms = ad198x_build_pcms, | ||
251 | .init = ad198x_init, | ||
252 | .free = ad198x_free, | ||
253 | #ifdef CONFIG_PM | ||
254 | .resume = ad198x_resume, | ||
255 | #endif | ||
256 | }; | ||
257 | |||
258 | |||
259 | /* | ||
260 | * AD1986A specific | ||
261 | */ | ||
262 | |||
37 | #define AD1986A_SPDIF_OUT 0x02 | 263 | #define AD1986A_SPDIF_OUT 0x02 |
38 | #define AD1986A_FRONT_DAC 0x03 | 264 | #define AD1986A_FRONT_DAC 0x03 |
39 | #define AD1986A_SURR_DAC 0x04 | 265 | #define AD1986A_SURR_DAC 0x04 |
@@ -68,7 +294,7 @@ static struct hda_input_mux ad1986a_capture_source = { | |||
68 | static int ad1986a_pcm_amp_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | 294 | static int ad1986a_pcm_amp_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) |
69 | { | 295 | { |
70 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 296 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
71 | struct ad1986a_spec *ad = codec->spec; | 297 | struct ad198x_spec *ad = codec->spec; |
72 | 298 | ||
73 | down(&ad->amp_mutex); | 299 | down(&ad->amp_mutex); |
74 | snd_hda_mixer_amp_volume_get(kcontrol, ucontrol); | 300 | snd_hda_mixer_amp_volume_get(kcontrol, ucontrol); |
@@ -79,7 +305,7 @@ static int ad1986a_pcm_amp_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_ | |||
79 | static int ad1986a_pcm_amp_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | 305 | static int ad1986a_pcm_amp_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) |
80 | { | 306 | { |
81 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 307 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
82 | struct ad1986a_spec *ad = codec->spec; | 308 | struct ad198x_spec *ad = codec->spec; |
83 | int i, change = 0; | 309 | int i, change = 0; |
84 | 310 | ||
85 | down(&ad->amp_mutex); | 311 | down(&ad->amp_mutex); |
@@ -97,7 +323,7 @@ static int ad1986a_pcm_amp_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_ | |||
97 | static int ad1986a_pcm_amp_sw_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | 323 | static int ad1986a_pcm_amp_sw_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) |
98 | { | 324 | { |
99 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 325 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
100 | struct ad1986a_spec *ad = codec->spec; | 326 | struct ad198x_spec *ad = codec->spec; |
101 | 327 | ||
102 | down(&ad->amp_mutex); | 328 | down(&ad->amp_mutex); |
103 | snd_hda_mixer_amp_switch_get(kcontrol, ucontrol); | 329 | snd_hda_mixer_amp_switch_get(kcontrol, ucontrol); |
@@ -108,7 +334,7 @@ static int ad1986a_pcm_amp_sw_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t | |||
108 | static int ad1986a_pcm_amp_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | 334 | static int ad1986a_pcm_amp_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) |
109 | { | 335 | { |
110 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 336 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
111 | struct ad1986a_spec *ad = codec->spec; | 337 | struct ad198x_spec *ad = codec->spec; |
112 | int i, change = 0; | 338 | int i, change = 0; |
113 | 339 | ||
114 | down(&ad->amp_mutex); | 340 | down(&ad->amp_mutex); |
@@ -122,32 +348,6 @@ static int ad1986a_pcm_amp_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t | |||
122 | } | 348 | } |
123 | 349 | ||
124 | /* | 350 | /* |
125 | * input MUX handling | ||
126 | */ | ||
127 | static int ad1986a_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) | ||
128 | { | ||
129 | return snd_hda_input_mux_info(&ad1986a_capture_source, uinfo); | ||
130 | } | ||
131 | |||
132 | static int ad1986a_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
133 | { | ||
134 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
135 | struct ad1986a_spec *spec = codec->spec; | ||
136 | |||
137 | ucontrol->value.enumerated.item[0] = spec->cur_mux; | ||
138 | return 0; | ||
139 | } | ||
140 | |||
141 | static int ad1986a_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
142 | { | ||
143 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
144 | struct ad1986a_spec *spec = codec->spec; | ||
145 | |||
146 | return snd_hda_input_mux_put(codec, &ad1986a_capture_source, ucontrol, | ||
147 | AD1986A_ADC, &spec->cur_mux); | ||
148 | } | ||
149 | |||
150 | /* | ||
151 | * mixers | 351 | * mixers |
152 | */ | 352 | */ |
153 | static snd_kcontrol_new_t ad1986a_mixers[] = { | 353 | static snd_kcontrol_new_t ad1986a_mixers[] = { |
@@ -194,9 +394,9 @@ static snd_kcontrol_new_t ad1986a_mixers[] = { | |||
194 | { | 394 | { |
195 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 395 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
196 | .name = "Capture Source", | 396 | .name = "Capture Source", |
197 | .info = ad1986a_mux_enum_info, | 397 | .info = ad198x_mux_enum_info, |
198 | .get = ad1986a_mux_enum_get, | 398 | .get = ad198x_mux_enum_get, |
199 | .put = ad1986a_mux_enum_put, | 399 | .put = ad198x_mux_enum_put, |
200 | }, | 400 | }, |
201 | HDA_CODEC_MUTE("Stereo Downmix Switch", 0x09, 0x0, HDA_OUTPUT), | 401 | HDA_CODEC_MUTE("Stereo Downmix Switch", 0x09, 0x0, HDA_OUTPUT), |
202 | { } /* end */ | 402 | { } /* end */ |
@@ -241,183 +441,328 @@ static struct hda_verb ad1986a_init_verbs[] = { | |||
241 | {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | 441 | {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, |
242 | {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | 442 | {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, |
243 | {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | 443 | {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, |
444 | /* HP Pin */ | ||
445 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, | ||
446 | /* Front, Surround, CLFE Pins */ | ||
447 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, | ||
448 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, | ||
449 | {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, | ||
450 | /* Mono Pin */ | ||
451 | {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, | ||
452 | /* Mic Pin */ | ||
453 | {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, | ||
454 | /* Line, Aux, CD, Beep-In Pin */ | ||
455 | {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, | ||
456 | {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, | ||
457 | {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, | ||
458 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, | ||
459 | {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, | ||
244 | { } /* end */ | 460 | { } /* end */ |
245 | }; | 461 | }; |
246 | 462 | ||
247 | 463 | ||
248 | static int ad1986a_init(struct hda_codec *codec) | 464 | static int patch_ad1986a(struct hda_codec *codec) |
249 | { | 465 | { |
250 | snd_hda_sequence_write(codec, ad1986a_init_verbs); | 466 | struct ad198x_spec *spec; |
251 | return 0; | ||
252 | } | ||
253 | 467 | ||
254 | static int ad1986a_build_controls(struct hda_codec *codec) | 468 | spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); |
255 | { | 469 | if (spec == NULL) |
256 | int err; | 470 | return -ENOMEM; |
471 | |||
472 | init_MUTEX(&spec->amp_mutex); | ||
473 | codec->spec = spec; | ||
474 | |||
475 | spec->multiout.max_channels = 6; | ||
476 | spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids); | ||
477 | spec->multiout.dac_nids = ad1986a_dac_nids; | ||
478 | spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT; | ||
479 | spec->adc_nid = AD1986A_ADC; | ||
480 | spec->input_mux = &ad1986a_capture_source; | ||
481 | spec->mixers = ad1986a_mixers; | ||
482 | spec->init_verbs = ad1986a_init_verbs; | ||
483 | |||
484 | codec->patch_ops = ad198x_patch_ops; | ||
257 | 485 | ||
258 | err = snd_hda_add_new_ctls(codec, ad1986a_mixers); | ||
259 | if (err < 0) | ||
260 | return err; | ||
261 | err = snd_hda_create_spdif_out_ctls(codec, AD1986A_SPDIF_OUT); | ||
262 | if (err < 0) | ||
263 | return err; | ||
264 | return 0; | 486 | return 0; |
265 | } | 487 | } |
266 | 488 | ||
267 | /* | 489 | /* |
268 | * Analog playback callbacks | 490 | * AD1983 specific |
269 | */ | 491 | */ |
270 | static int ad1986a_playback_pcm_open(struct hda_pcm_stream *hinfo, | ||
271 | struct hda_codec *codec, | ||
272 | snd_pcm_substream_t *substream) | ||
273 | { | ||
274 | struct ad1986a_spec *spec = codec->spec; | ||
275 | return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream); | ||
276 | } | ||
277 | 492 | ||
278 | static int ad1986a_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | 493 | #define AD1983_SPDIF_OUT 0x02 |
279 | struct hda_codec *codec, | 494 | #define AD1983_DAC 0x03 |
280 | unsigned int stream_tag, | 495 | #define AD1983_ADC 0x04 |
281 | unsigned int format, | ||
282 | snd_pcm_substream_t *substream) | ||
283 | { | ||
284 | struct ad1986a_spec *spec = codec->spec; | ||
285 | return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag, | ||
286 | format, substream); | ||
287 | } | ||
288 | 496 | ||
289 | static int ad1986a_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, | 497 | static hda_nid_t ad1983_dac_nids[1] = { AD1983_DAC }; |
290 | struct hda_codec *codec, | 498 | |
291 | snd_pcm_substream_t *substream) | 499 | static struct hda_input_mux ad1983_capture_source = { |
292 | { | 500 | .num_items = 4, |
293 | struct ad1986a_spec *spec = codec->spec; | 501 | .items = { |
294 | return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout); | 502 | { "Mic", 0x0 }, |
295 | } | 503 | { "Line", 0x1 }, |
504 | { "Mix", 0x2 }, | ||
505 | { "Mix Mono", 0x3 }, | ||
506 | }, | ||
507 | }; | ||
296 | 508 | ||
297 | /* | 509 | /* |
298 | * Digital out | 510 | * SPDIF playback route |
299 | */ | 511 | */ |
300 | static int ad1986a_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, | 512 | static int ad1983_spdif_route_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) |
301 | struct hda_codec *codec, | ||
302 | snd_pcm_substream_t *substream) | ||
303 | { | 513 | { |
304 | struct ad1986a_spec *spec = codec->spec; | 514 | static char *texts[] = { "PCM", "ADC" }; |
305 | return snd_hda_multi_out_dig_open(codec, &spec->multiout); | 515 | |
516 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
517 | uinfo->count = 1; | ||
518 | uinfo->value.enumerated.items = 2; | ||
519 | if (uinfo->value.enumerated.item > 1) | ||
520 | uinfo->value.enumerated.item = 1; | ||
521 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); | ||
522 | return 0; | ||
306 | } | 523 | } |
307 | 524 | ||
308 | static int ad1986a_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, | 525 | static int ad1983_spdif_route_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) |
309 | struct hda_codec *codec, | ||
310 | snd_pcm_substream_t *substream) | ||
311 | { | 526 | { |
312 | struct ad1986a_spec *spec = codec->spec; | 527 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
313 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | 528 | struct ad198x_spec *spec = codec->spec; |
314 | } | ||
315 | 529 | ||
316 | /* | 530 | ucontrol->value.enumerated.item[0] = spec->spdif_route; |
317 | * Analog capture | ||
318 | */ | ||
319 | static int ad1986a_capture_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
320 | struct hda_codec *codec, | ||
321 | unsigned int stream_tag, | ||
322 | unsigned int format, | ||
323 | snd_pcm_substream_t *substream) | ||
324 | { | ||
325 | snd_hda_codec_setup_stream(codec, AD1986A_ADC, stream_tag, 0, format); | ||
326 | return 0; | 531 | return 0; |
327 | } | 532 | } |
328 | 533 | ||
329 | static int ad1986a_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, | 534 | static int ad1983_spdif_route_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) |
330 | struct hda_codec *codec, | ||
331 | snd_pcm_substream_t *substream) | ||
332 | { | 535 | { |
333 | snd_hda_codec_setup_stream(codec, AD1986A_ADC, 0, 0, 0); | 536 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
537 | struct ad198x_spec *spec = codec->spec; | ||
538 | |||
539 | if (spec->spdif_route != ucontrol->value.enumerated.item[0]) { | ||
540 | spec->spdif_route = ucontrol->value.enumerated.item[0]; | ||
541 | snd_hda_codec_write(codec, spec->multiout.dig_out_nid, 0, | ||
542 | AC_VERB_SET_CONNECT_SEL, spec->spdif_route); | ||
543 | return 1; | ||
544 | } | ||
334 | return 0; | 545 | return 0; |
335 | } | 546 | } |
336 | 547 | ||
337 | 548 | static snd_kcontrol_new_t ad1983_mixers[] = { | |
338 | /* | 549 | HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT), |
339 | */ | 550 | HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT), |
340 | static struct hda_pcm_stream ad1986a_pcm_analog_playback = { | 551 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT), |
341 | .substreams = 1, | 552 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT), |
342 | .channels_min = 2, | 553 | HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT), |
343 | .channels_max = 6, | 554 | HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT), |
344 | .nid = AD1986A_FRONT_DAC, /* NID to query formats and rates */ | 555 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT), |
345 | .ops = { | 556 | HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT), |
346 | .open = ad1986a_playback_pcm_open, | 557 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT), |
347 | .prepare = ad1986a_playback_pcm_prepare, | 558 | HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT), |
348 | .cleanup = ad1986a_playback_pcm_cleanup | 559 | HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT), |
560 | HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT), | ||
561 | HDA_CODEC_VOLUME_MONO("PC Speaker Playback Volume", 0x10, 1, 0x0, HDA_OUTPUT), | ||
562 | HDA_CODEC_MUTE_MONO("PC Speaker Playback Switch", 0x10, 1, 0x0, HDA_OUTPUT), | ||
563 | HDA_CODEC_VOLUME("Mic Boost", 0x0c, 0x0, HDA_OUTPUT), | ||
564 | HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), | ||
565 | HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT), | ||
566 | { | ||
567 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
568 | .name = "Capture Source", | ||
569 | .info = ad198x_mux_enum_info, | ||
570 | .get = ad198x_mux_enum_get, | ||
571 | .put = ad198x_mux_enum_put, | ||
349 | }, | 572 | }, |
350 | }; | 573 | { |
351 | 574 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | |
352 | static struct hda_pcm_stream ad1986a_pcm_analog_capture = { | 575 | .name = "IEC958 Playback Route", |
353 | .substreams = 2, | 576 | .info = ad1983_spdif_route_info, |
354 | .channels_min = 2, | 577 | .get = ad1983_spdif_route_get, |
355 | .channels_max = 2, | 578 | .put = ad1983_spdif_route_put, |
356 | .nid = AD1986A_ADC, /* NID to query formats and rates */ | ||
357 | .ops = { | ||
358 | .prepare = ad1986a_capture_pcm_prepare, | ||
359 | .cleanup = ad1986a_capture_pcm_cleanup | ||
360 | }, | 579 | }, |
580 | { } /* end */ | ||
361 | }; | 581 | }; |
362 | 582 | ||
363 | static struct hda_pcm_stream ad1986a_pcm_digital_playback = { | 583 | static struct hda_verb ad1983_init_verbs[] = { |
364 | .substreams = 1, | 584 | /* Front, HP, Mono; mute as default */ |
365 | .channels_min = 2, | 585 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, |
366 | .channels_max = 2, | 586 | {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, |
367 | .nid = AD1986A_SPDIF_OUT, | 587 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, |
368 | .ops = { | 588 | /* Beep, PCM, Mic, Line-In: mute */ |
369 | .open = ad1986a_dig_playback_pcm_open, | 589 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, |
370 | .close = ad1986a_dig_playback_pcm_close | 590 | {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, |
371 | }, | 591 | {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, |
592 | {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
593 | /* Front, HP selectors; from Mix */ | ||
594 | {0x05, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
595 | {0x06, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
596 | /* Mono selector; from Mix */ | ||
597 | {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03}, | ||
598 | /* Mic selector; Mic */ | ||
599 | {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
600 | /* Line-in selector: Line-in */ | ||
601 | {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
602 | /* Mic boost: 0dB */ | ||
603 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
604 | /* Record selector: mic */ | ||
605 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
606 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
607 | /* SPDIF route: PCM */ | ||
608 | {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
609 | /* Front Pin */ | ||
610 | {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, | ||
611 | /* HP Pin */ | ||
612 | {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, | ||
613 | /* Mono Pin */ | ||
614 | {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, | ||
615 | /* Mic Pin */ | ||
616 | {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, | ||
617 | /* Line Pin */ | ||
618 | {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, | ||
619 | { } /* end */ | ||
372 | }; | 620 | }; |
373 | 621 | ||
374 | static int ad1986a_build_pcms(struct hda_codec *codec) | 622 | static int patch_ad1983(struct hda_codec *codec) |
375 | { | 623 | { |
376 | struct ad1986a_spec *spec = codec->spec; | 624 | struct ad198x_spec *spec; |
377 | struct hda_pcm *info = spec->pcm_rec; | ||
378 | 625 | ||
379 | codec->num_pcms = 2; | 626 | spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); |
380 | codec->pcm_info = info; | 627 | if (spec == NULL) |
628 | return -ENOMEM; | ||
381 | 629 | ||
382 | info->name = "AD1986A Analog"; | 630 | init_MUTEX(&spec->amp_mutex); |
383 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad1986a_pcm_analog_playback; | 631 | codec->spec = spec; |
384 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad1986a_pcm_analog_capture; | 632 | |
385 | info++; | 633 | spec->multiout.max_channels = 2; |
634 | spec->multiout.num_dacs = ARRAY_SIZE(ad1983_dac_nids); | ||
635 | spec->multiout.dac_nids = ad1983_dac_nids; | ||
636 | spec->multiout.dig_out_nid = AD1983_SPDIF_OUT; | ||
637 | spec->adc_nid = AD1983_ADC; | ||
638 | spec->input_mux = &ad1983_capture_source; | ||
639 | spec->mixers = ad1983_mixers; | ||
640 | spec->init_verbs = ad1983_init_verbs; | ||
641 | spec->spdif_route = 0; | ||
386 | 642 | ||
387 | info->name = "AD1986A Digital"; | 643 | codec->patch_ops = ad198x_patch_ops; |
388 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad1986a_pcm_digital_playback; | ||
389 | 644 | ||
390 | return 0; | 645 | return 0; |
391 | } | 646 | } |
392 | 647 | ||
393 | static void ad1986a_free(struct hda_codec *codec) | ||
394 | { | ||
395 | kfree(codec->spec); | ||
396 | } | ||
397 | 648 | ||
398 | #ifdef CONFIG_PM | 649 | /* |
399 | static int ad1986a_resume(struct hda_codec *codec) | 650 | * AD1981 HD specific |
400 | { | 651 | */ |
401 | ad1986a_init(codec); | ||
402 | snd_hda_resume_ctls(codec, ad1986a_mixers); | ||
403 | snd_hda_resume_spdif_out(codec); | ||
404 | return 0; | ||
405 | } | ||
406 | #endif | ||
407 | 652 | ||
408 | static struct hda_codec_ops ad1986a_patch_ops = { | 653 | #define AD1981_SPDIF_OUT 0x02 |
409 | .build_controls = ad1986a_build_controls, | 654 | #define AD1981_DAC 0x03 |
410 | .build_pcms = ad1986a_build_pcms, | 655 | #define AD1981_ADC 0x04 |
411 | .init = ad1986a_init, | 656 | |
412 | .free = ad1986a_free, | 657 | static hda_nid_t ad1981_dac_nids[1] = { AD1981_DAC }; |
413 | #ifdef CONFIG_PM | 658 | |
414 | .resume = ad1986a_resume, | 659 | /* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */ |
415 | #endif | 660 | static struct hda_input_mux ad1981_capture_source = { |
661 | .num_items = 7, | ||
662 | .items = { | ||
663 | { "Front Mic", 0x0 }, | ||
664 | { "Line", 0x1 }, | ||
665 | { "Mix", 0x2 }, | ||
666 | { "Mix Mono", 0x3 }, | ||
667 | { "CD", 0x4 }, | ||
668 | { "Mic", 0x6 }, | ||
669 | { "Aux", 0x7 }, | ||
670 | }, | ||
416 | }; | 671 | }; |
417 | 672 | ||
418 | static int patch_ad1986a(struct hda_codec *codec) | 673 | static snd_kcontrol_new_t ad1981_mixers[] = { |
674 | HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT), | ||
675 | HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT), | ||
676 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT), | ||
677 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT), | ||
678 | HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT), | ||
679 | HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT), | ||
680 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT), | ||
681 | HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT), | ||
682 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT), | ||
683 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT), | ||
684 | HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT), | ||
685 | HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT), | ||
686 | HDA_CODEC_VOLUME("Aux Playback Volume", 0x1b, 0x0, HDA_OUTPUT), | ||
687 | HDA_CODEC_MUTE("Aux Playback Switch", 0x1b, 0x0, HDA_OUTPUT), | ||
688 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT), | ||
689 | HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT), | ||
690 | HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT), | ||
691 | HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT), | ||
692 | HDA_CODEC_VOLUME_MONO("PC Speaker Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT), | ||
693 | HDA_CODEC_MUTE_MONO("PC Speaker Playback Switch", 0x0d, 1, 0x0, HDA_OUTPUT), | ||
694 | HDA_CODEC_VOLUME("Front Mic Boost", 0x08, 0x0, HDA_INPUT), | ||
695 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x0, HDA_INPUT), | ||
696 | HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), | ||
697 | HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT), | ||
698 | { | ||
699 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
700 | .name = "Capture Source", | ||
701 | .info = ad198x_mux_enum_info, | ||
702 | .get = ad198x_mux_enum_get, | ||
703 | .put = ad198x_mux_enum_put, | ||
704 | }, | ||
705 | /* identical with AD1983 */ | ||
706 | { | ||
707 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
708 | .name = "IEC958 Playback Route", | ||
709 | .info = ad1983_spdif_route_info, | ||
710 | .get = ad1983_spdif_route_get, | ||
711 | .put = ad1983_spdif_route_put, | ||
712 | }, | ||
713 | { } /* end */ | ||
714 | }; | ||
715 | |||
716 | static struct hda_verb ad1981_init_verbs[] = { | ||
717 | /* Front, HP, Mono; mute as default */ | ||
718 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
719 | {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
720 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
721 | /* Beep, PCM, Front Mic, Line, Rear Mic, Aux, CD-In: mute */ | ||
722 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
723 | {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
724 | {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
725 | {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
726 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
727 | {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
728 | {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
729 | /* Front, HP selectors; from Mix */ | ||
730 | {0x05, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
731 | {0x06, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
732 | /* Mono selector; from Mix */ | ||
733 | {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03}, | ||
734 | /* Mic Mixer; select Front Mic */ | ||
735 | {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
736 | {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
737 | /* Mic boost: 0dB */ | ||
738 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
739 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
740 | /* Record selector: Front mic */ | ||
741 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
742 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
743 | /* SPDIF route: PCM */ | ||
744 | {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
745 | /* Front Pin */ | ||
746 | {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, | ||
747 | /* HP Pin */ | ||
748 | {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, | ||
749 | /* Mono Pin */ | ||
750 | {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, | ||
751 | /* Front & Rear Mic Pins */ | ||
752 | {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, | ||
753 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, | ||
754 | /* Line Pin */ | ||
755 | {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, | ||
756 | /* Digital Beep */ | ||
757 | {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
758 | /* Line-Out as Input: disabled */ | ||
759 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
760 | { } /* end */ | ||
761 | }; | ||
762 | |||
763 | static int patch_ad1981(struct hda_codec *codec) | ||
419 | { | 764 | { |
420 | struct ad1986a_spec *spec; | 765 | struct ad198x_spec *spec; |
421 | 766 | ||
422 | spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); | 767 | spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); |
423 | if (spec == NULL) | 768 | if (spec == NULL) |
@@ -426,20 +771,28 @@ static int patch_ad1986a(struct hda_codec *codec) | |||
426 | init_MUTEX(&spec->amp_mutex); | 771 | init_MUTEX(&spec->amp_mutex); |
427 | codec->spec = spec; | 772 | codec->spec = spec; |
428 | 773 | ||
429 | spec->multiout.max_channels = 6; | 774 | spec->multiout.max_channels = 2; |
430 | spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids); | 775 | spec->multiout.num_dacs = ARRAY_SIZE(ad1981_dac_nids); |
431 | spec->multiout.dac_nids = ad1986a_dac_nids; | 776 | spec->multiout.dac_nids = ad1981_dac_nids; |
432 | spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT; | 777 | spec->multiout.dig_out_nid = AD1981_SPDIF_OUT; |
778 | spec->adc_nid = AD1981_ADC; | ||
779 | spec->input_mux = &ad1981_capture_source; | ||
780 | spec->mixers = ad1981_mixers; | ||
781 | spec->init_verbs = ad1981_init_verbs; | ||
782 | spec->spdif_route = 0; | ||
433 | 783 | ||
434 | codec->patch_ops = ad1986a_patch_ops; | 784 | codec->patch_ops = ad198x_patch_ops; |
435 | 785 | ||
436 | return 0; | 786 | return 0; |
437 | } | 787 | } |
438 | 788 | ||
789 | |||
439 | /* | 790 | /* |
440 | * patch entries | 791 | * patch entries |
441 | */ | 792 | */ |
442 | struct hda_codec_preset snd_hda_preset_analog[] = { | 793 | struct hda_codec_preset snd_hda_preset_analog[] = { |
794 | { .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 }, | ||
795 | { .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 }, | ||
443 | { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a }, | 796 | { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a }, |
444 | {} /* terminator */ | 797 | {} /* terminator */ |
445 | }; | 798 | }; |