aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/hda_jack.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2011-12-01 11:41:36 -0500
committerTakashi Iwai <tiwai@suse.de>2011-12-01 11:47:54 -0500
commit31ef22579302ac42054bebecb528710f46580925 (patch)
tree8f521b4920f0a1ebbb1e6f9105948a5f38f24404 /sound/pci/hda/hda_jack.c
parent358b6e62b86f6313d114e0f6b7d8f8adaf85ed9c (diff)
ALSA: hda - Integrate input-jack stuff into kctl-jack
Instead of managing input-jack stuff separately, call all stuff inside the kctl-jack creation, deletion and report. The caller no longer needs to care about input-jack. The better integration between input-jack and kctl-jack should be done in the upper layer in near future, but for now, it's implemented locally for more tests. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/hda_jack.c')
-rw-r--r--sound/pci/hda/hda_jack.c159
1 files changed, 60 insertions, 99 deletions
diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c
index 394901515d9e..d8a35da0803f 100644
--- a/sound/pci/hda/hda_jack.c
+++ b/sound/pci/hda/hda_jack.c
@@ -90,15 +90,19 @@ snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid)
90} 90}
91EXPORT_SYMBOL_HDA(snd_hda_jack_tbl_new); 91EXPORT_SYMBOL_HDA(snd_hda_jack_tbl_new);
92 92
93#ifdef CONFIG_SND_HDA_INPUT_JACK
94static void snd_hda_input_jack_free(struct hda_codec *codec);
95#else
96#define snd_hda_input_jack_free(codec)
97#endif
98
99void snd_hda_jack_tbl_clear(struct hda_codec *codec) 93void snd_hda_jack_tbl_clear(struct hda_codec *codec)
100{ 94{
101 snd_hda_input_jack_free(codec); 95#ifdef CONFIG_SND_HDA_INPUT_JACK
96 /* free jack instances manually when clearing/reconfiguring */
97 if (!codec->bus->shutdown && codec->jacktbl.list) {
98 struct hda_jack_tbl *jack = codec->jacktbl.list;
99 int i;
100 for (i = 0; i < codec->jacktbl.used; i++, jack++) {
101 if (jack->jack)
102 snd_device_free(codec->bus->card, jack->jack);
103 }
104 }
105#endif
102 snd_array_free(&codec->jacktbl); 106 snd_array_free(&codec->jacktbl);
103} 107}
104 108
@@ -199,10 +203,44 @@ void snd_hda_jack_report_sync(struct hda_codec *codec)
199 continue; 203 continue;
200 state = get_jack_plug_state(jack->pin_sense); 204 state = get_jack_plug_state(jack->pin_sense);
201 snd_kctl_jack_report(codec->bus->card, jack->kctl, state); 205 snd_kctl_jack_report(codec->bus->card, jack->kctl, state);
206#ifdef CONFIG_SND_HDA_INPUT_JACK
207 if (jack->jack)
208 snd_jack_report(jack->jack,
209 state ? jack->type : 0);
210#endif
202 } 211 }
203} 212}
204EXPORT_SYMBOL_HDA(snd_hda_jack_report_sync); 213EXPORT_SYMBOL_HDA(snd_hda_jack_report_sync);
205 214
215#ifdef CONFIG_SND_HDA_INPUT_JACK
216/* guess the jack type from the pin-config */
217static int get_input_jack_type(struct hda_codec *codec, hda_nid_t nid)
218{
219 unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid);
220 switch (get_defcfg_device(def_conf)) {
221 case AC_JACK_LINE_OUT:
222 case AC_JACK_SPEAKER:
223 return SND_JACK_LINEOUT;
224 case AC_JACK_HP_OUT:
225 return SND_JACK_HEADPHONE;
226 case AC_JACK_SPDIF_OUT:
227 case AC_JACK_DIG_OTHER_OUT:
228 return SND_JACK_AVOUT;
229 case AC_JACK_MIC_IN:
230 return SND_JACK_MICROPHONE;
231 default:
232 return SND_JACK_LINEIN;
233 }
234}
235
236static void hda_free_jack_priv(struct snd_jack *jack)
237{
238 struct hda_jack_tbl *jacks = jack->private_data;
239 jacks->nid = 0;
240 jacks->jack = NULL;
241}
242#endif
243
206/** 244/**
207 * snd_hda_jack_add_kctl - Add a kctl for the given pin 245 * snd_hda_jack_add_kctl - Add a kctl for the given pin
208 * 246 *
@@ -214,6 +252,7 @@ int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,
214{ 252{
215 struct hda_jack_tbl *jack; 253 struct hda_jack_tbl *jack;
216 struct snd_kcontrol *kctl; 254 struct snd_kcontrol *kctl;
255 int err, state;
217 256
218 jack = snd_hda_jack_tbl_new(codec, nid); 257 jack = snd_hda_jack_tbl_new(codec, nid);
219 if (!jack) 258 if (!jack)
@@ -223,11 +262,21 @@ int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,
223 kctl = snd_kctl_jack_new(name, idx, codec); 262 kctl = snd_kctl_jack_new(name, idx, codec);
224 if (!kctl) 263 if (!kctl)
225 return -ENOMEM; 264 return -ENOMEM;
226 if (snd_hda_ctl_add(codec, nid, kctl) < 0) 265 err = snd_hda_ctl_add(codec, nid, kctl);
227 return -ENOMEM; 266 if (err < 0)
267 return err;
228 jack->kctl = kctl; 268 jack->kctl = kctl;
229 snd_kctl_jack_report(codec->bus->card, kctl, 269 state = snd_hda_jack_detect(codec, nid);
230 snd_hda_jack_detect(codec, nid)); 270 snd_kctl_jack_report(codec->bus->card, kctl, state);
271#ifdef CONFIG_SND_HDA_INPUT_JACK
272 jack->type = get_input_jack_type(codec, nid);
273 err = snd_jack_new(codec->bus->card, name, jack->type, &jack->jack);
274 if (err < 0)
275 return err;
276 jack->jack->private_data = jack;
277 jack->jack->private_free = hda_free_jack_priv;
278 snd_jack_report(jack->jack, state ? jack->type : 0);
279#endif
231 return 0; 280 return 0;
232} 281}
233EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctl); 282EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctl);
@@ -302,91 +351,3 @@ int snd_hda_jack_add_kctls(struct hda_codec *codec,
302 return 0; 351 return 0;
303} 352}
304EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctls); 353EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctls);
305
306#ifdef CONFIG_SND_HDA_INPUT_JACK
307/*
308 * Input-jack notification support
309 */
310static const char *get_jack_default_name(struct hda_codec *codec, hda_nid_t nid,
311 int type)
312{
313 switch (type) {
314 case SND_JACK_HEADPHONE:
315 return "Headphone";
316 case SND_JACK_MICROPHONE:
317 return "Mic";
318 case SND_JACK_LINEOUT:
319 return "Line-out";
320 case SND_JACK_LINEIN:
321 return "Line-in";
322 case SND_JACK_HEADSET:
323 return "Headset";
324 case SND_JACK_VIDEOOUT:
325 return "HDMI/DP";
326 default:
327 return "Misc";
328 }
329}
330
331static void hda_free_jack_priv(struct snd_jack *jack)
332{
333 struct hda_jack_tbl *jacks = jack->private_data;
334 jacks->nid = 0;
335 jacks->jack = NULL;
336}
337
338int snd_hda_input_jack_add(struct hda_codec *codec, hda_nid_t nid, int type,
339 const char *name)
340{
341 struct hda_jack_tbl *jack = snd_hda_jack_tbl_new(codec, nid);
342 int err;
343
344 if (!jack)
345 return -ENOMEM;
346 if (!name)
347 name = get_jack_default_name(codec, nid, type);
348 err = snd_jack_new(codec->bus->card, name, type, &jack->jack);
349 if (err < 0)
350 return err;
351 jack->type = type;
352 jack->jack->private_data = jack;
353 jack->jack->private_free = hda_free_jack_priv;
354 return 0;
355}
356EXPORT_SYMBOL_HDA(snd_hda_input_jack_add);
357
358void snd_hda_input_jack_report(struct hda_codec *codec, hda_nid_t nid)
359{
360 struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid);
361 unsigned int pin_ctl;
362 unsigned int present;
363 int type;
364
365 if (!jack || !jack->jack)
366 return;
367
368 present = snd_hda_jack_detect(codec, nid);
369 type = jack->type;
370 if (type == (SND_JACK_HEADPHONE | SND_JACK_LINEOUT)) {
371 pin_ctl = snd_hda_codec_read(codec, nid, 0,
372 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
373 type = (pin_ctl & AC_PINCTL_HP_EN) ?
374 SND_JACK_HEADPHONE : SND_JACK_LINEOUT;
375 }
376 snd_jack_report(jack->jack, present ? type : 0);
377}
378EXPORT_SYMBOL_HDA(snd_hda_input_jack_report);
379
380/* free jack instances manually when clearing/reconfiguring */
381static void snd_hda_input_jack_free(struct hda_codec *codec)
382{
383 if (!codec->bus->shutdown && codec->jacktbl.list) {
384 struct hda_jack_tbl *jack = codec->jacktbl.list;
385 int i;
386 for (i = 0; i < codec->jacktbl.used; i++, jack++) {
387 if (jack->jack)
388 snd_device_free(codec->bus->card, jack->jack);
389 }
390 }
391}
392#endif /* CONFIG_SND_HDA_INPUT_JACK */