aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sound/control.h8
-rw-r--r--sound/core/Kconfig3
-rw-r--r--sound/core/Makefile1
-rw-r--r--sound/core/ctljack.c55
-rw-r--r--sound/pci/hda/Kconfig1
-rw-r--r--sound/pci/hda/hda_jack.c56
-rw-r--r--sound/pci/hda/hda_jack.h1
7 files changed, 76 insertions, 49 deletions
diff --git a/include/sound/control.h b/include/sound/control.h
index 1a94a216ed99..b2796e83c7ac 100644
--- a/include/sound/control.h
+++ b/include/sound/control.h
@@ -227,4 +227,12 @@ snd_ctl_add_slave_uncached(struct snd_kcontrol *master,
227 return _snd_ctl_add_slave(master, slave, SND_CTL_SLAVE_NEED_UPDATE); 227 return _snd_ctl_add_slave(master, slave, SND_CTL_SLAVE_NEED_UPDATE);
228} 228}
229 229
230/*
231 * Helper functions for jack-detection controls
232 */
233struct snd_kcontrol *
234snd_kctl_jack_new(const char *name, int idx, void *private_data);
235void snd_kctl_jack_report(struct snd_card *card,
236 struct snd_kcontrol *kctl, bool status);
237
230#endif /* __SOUND_CONTROL_H */ 238#endif /* __SOUND_CONTROL_H */
diff --git a/sound/core/Kconfig b/sound/core/Kconfig
index 475455c76610..66f287f2f759 100644
--- a/sound/core/Kconfig
+++ b/sound/core/Kconfig
@@ -207,6 +207,9 @@ config SND_PCM_XRUN_DEBUG
207config SND_VMASTER 207config SND_VMASTER
208 bool 208 bool
209 209
210config SND_KCTL_JACK
211 bool
212
210config SND_DMA_SGBUF 213config SND_DMA_SGBUF
211 def_bool y 214 def_bool y
212 depends on X86 215 depends on X86
diff --git a/sound/core/Makefile b/sound/core/Makefile
index 350a08d277f4..b4637c3e776e 100644
--- a/sound/core/Makefile
+++ b/sound/core/Makefile
@@ -7,6 +7,7 @@ snd-y := sound.o init.o memory.o info.o control.o misc.o device.o
7snd-$(CONFIG_ISA_DMA_API) += isadma.o 7snd-$(CONFIG_ISA_DMA_API) += isadma.o
8snd-$(CONFIG_SND_OSSEMUL) += sound_oss.o info_oss.o 8snd-$(CONFIG_SND_OSSEMUL) += sound_oss.o info_oss.o
9snd-$(CONFIG_SND_VMASTER) += vmaster.o 9snd-$(CONFIG_SND_VMASTER) += vmaster.o
10snd-$(CONFIG_SND_KCTL_JACK) += ctljack.o
10snd-$(CONFIG_SND_JACK) += jack.o 11snd-$(CONFIG_SND_JACK) += jack.o
11 12
12snd-pcm-objs := pcm.o pcm_native.o pcm_lib.o pcm_timer.o pcm_misc.o \ 13snd-pcm-objs := pcm.o pcm_native.o pcm_lib.o pcm_timer.o pcm_misc.o \
diff --git a/sound/core/ctljack.c b/sound/core/ctljack.c
new file mode 100644
index 000000000000..af0e78a3809c
--- /dev/null
+++ b/sound/core/ctljack.c
@@ -0,0 +1,55 @@
1/*
2 * Helper functions for jack-detection kcontrols
3 *
4 * Copyright (c) 2011 Takashi Iwai <tiwai@suse.de>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
9 * any later version.
10 */
11
12#include <linux/kernel.h>
13#include <sound/core.h>
14#include <sound/control.h>
15
16#define jack_detect_kctl_info snd_ctl_boolean_mono_info
17
18static int jack_detect_kctl_get(struct snd_kcontrol *kcontrol,
19 struct snd_ctl_elem_value *ucontrol)
20{
21 ucontrol->value.integer.value[0] = kcontrol->private_value;
22 return 0;
23}
24
25static struct snd_kcontrol_new jack_detect_kctl = {
26 /* name is filled later */
27 .iface = SNDRV_CTL_ELEM_IFACE_CARD,
28 .access = SNDRV_CTL_ELEM_ACCESS_READ,
29 .info = jack_detect_kctl_info,
30 .get = jack_detect_kctl_get,
31};
32
33struct snd_kcontrol *
34snd_kctl_jack_new(const char *name, int idx, void *private_data)
35{
36 struct snd_kcontrol *kctl;
37 kctl = snd_ctl_new1(&jack_detect_kctl, private_data);
38 if (!kctl)
39 return NULL;
40 snprintf(kctl->id.name, sizeof(kctl->id.name), "%s Jack", name);
41 kctl->id.index = idx;
42 kctl->private_value = 0;
43 return kctl;
44}
45EXPORT_SYMBOL_GPL(snd_kctl_jack_new);
46
47void snd_kctl_jack_report(struct snd_card *card,
48 struct snd_kcontrol *kctl, bool status)
49{
50 if (kctl->private_value == status)
51 return;
52 kctl->private_value = status;
53 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);
54}
55EXPORT_SYMBOL_GPL(snd_kctl_jack_report);
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig
index bb7e102d6726..163b6b5de3eb 100644
--- a/sound/pci/hda/Kconfig
+++ b/sound/pci/hda/Kconfig
@@ -2,6 +2,7 @@ menuconfig SND_HDA_INTEL
2 tristate "Intel HD Audio" 2 tristate "Intel HD Audio"
3 select SND_PCM 3 select SND_PCM
4 select SND_VMASTER 4 select SND_VMASTER
5 select SND_KCTL_JACK
5 help 6 help
6 Say Y here to include support for Intel "High Definition 7 Say Y here to include support for Intel "High Definition
7 Audio" (Azalia) and its compatible devices. 8 Audio" (Azalia) and its compatible devices.
diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c
index 8829d5c83fec..a2ab52b27265 100644
--- a/sound/pci/hda/hda_jack.c
+++ b/sound/pci/hda/hda_jack.c
@@ -97,12 +97,8 @@ static void jack_detect_update(struct hda_codec *codec,
97 struct hda_jack_tbl *jack) 97 struct hda_jack_tbl *jack)
98{ 98{
99 if (jack->jack_dirty || !jack->jack_detect) { 99 if (jack->jack_dirty || !jack->jack_detect) {
100 unsigned int val = read_pin_sense(codec, jack->nid); 100 jack->pin_sense = read_pin_sense(codec, jack->nid);
101 jack->jack_dirty = 0; 101 jack->jack_dirty = 0;
102 if (val != jack->pin_sense) {
103 jack->need_notify = 1;
104 jack->pin_sense = val;
105 }
106 } 102 }
107} 103}
108 104
@@ -142,6 +138,8 @@ u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid)
142} 138}
143EXPORT_SYMBOL_HDA(snd_hda_pin_sense); 139EXPORT_SYMBOL_HDA(snd_hda_pin_sense);
144 140
141#define get_jack_plug_state(sense) !!(sense & AC_PINSENSE_PRESENCE)
142
145/** 143/**
146 * snd_hda_jack_detect - query pin Presence Detect status 144 * snd_hda_jack_detect - query pin Presence Detect status
147 * @codec: the CODEC to sense 145 * @codec: the CODEC to sense
@@ -152,7 +150,7 @@ EXPORT_SYMBOL_HDA(snd_hda_pin_sense);
152int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid) 150int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid)
153{ 151{
154 u32 sense = snd_hda_pin_sense(codec, nid); 152 u32 sense = snd_hda_pin_sense(codec, nid);
155 return !!(sense & AC_PINSENSE_PRESENCE); 153 return get_jack_plug_state(sense);
156} 154}
157EXPORT_SYMBOL_HDA(snd_hda_jack_detect); 155EXPORT_SYMBOL_HDA(snd_hda_jack_detect);
158 156
@@ -176,58 +174,23 @@ int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid,
176} 174}
177EXPORT_SYMBOL_HDA(snd_hda_jack_detect_enable); 175EXPORT_SYMBOL_HDA(snd_hda_jack_detect_enable);
178 176
179/* queue the notification when needed */
180static void jack_detect_report(struct hda_codec *codec,
181 struct hda_jack_tbl *jack)
182{
183 jack_detect_update(codec, jack);
184 if (jack->need_notify) {
185 snd_ctl_notify(codec->bus->card, SNDRV_CTL_EVENT_MASK_VALUE,
186 &jack->kctl->id);
187 jack->need_notify = 0;
188 }
189}
190
191/** 177/**
192 * snd_hda_jack_report_sync - sync the states of all jacks and report if changed 178 * snd_hda_jack_report_sync - sync the states of all jacks and report if changed
193 */ 179 */
194void snd_hda_jack_report_sync(struct hda_codec *codec) 180void snd_hda_jack_report_sync(struct hda_codec *codec)
195{ 181{
196 struct hda_jack_tbl *jack = codec->jacktbl.list; 182 struct hda_jack_tbl *jack = codec->jacktbl.list;
197 int i; 183 int i, state;
198 184
199 for (i = 0; i < codec->jacktbl.used; i++, jack++) 185 for (i = 0; i < codec->jacktbl.used; i++, jack++)
200 if (jack->nid) { 186 if (jack->nid) {
201 jack_detect_update(codec, jack); 187 jack_detect_update(codec, jack);
202 jack_detect_report(codec, jack); 188 state = get_jack_plug_state(jack->pin_sense);
189 snd_kctl_jack_notify(codec->bus->card, jack->kctl, state);
203 } 190 }
204} 191}
205EXPORT_SYMBOL_HDA(snd_hda_jack_report_sync); 192EXPORT_SYMBOL_HDA(snd_hda_jack_report_sync);
206 193
207/*
208 * jack-detection kcontrols
209 */
210
211#define jack_detect_kctl_info snd_ctl_boolean_mono_info
212
213static int jack_detect_kctl_get(struct snd_kcontrol *kcontrol,
214 struct snd_ctl_elem_value *ucontrol)
215{
216 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
217 hda_nid_t nid = kcontrol->private_value;
218
219 ucontrol->value.integer.value[0] = snd_hda_jack_detect(codec, nid);
220 return 0;
221}
222
223static struct snd_kcontrol_new jack_detect_kctl = {
224 /* name is filled later */
225 .iface = SNDRV_CTL_ELEM_IFACE_CARD,
226 .access = SNDRV_CTL_ELEM_ACCESS_READ,
227 .info = jack_detect_kctl_info,
228 .get = jack_detect_kctl_get,
229};
230
231/** 194/**
232 * snd_hda_jack_add_kctl - Add a kctl for the given pin 195 * snd_hda_jack_add_kctl - Add a kctl for the given pin
233 * 196 *
@@ -245,12 +208,9 @@ int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,
245 return 0; 208 return 0;
246 if (jack->kctl) 209 if (jack->kctl)
247 return 0; /* already created */ 210 return 0; /* already created */
248 kctl = snd_ctl_new1(&jack_detect_kctl, codec); 211 kctl = snd_kctl_jack_new(name, idx, codec);
249 if (!kctl) 212 if (!kctl)
250 return -ENOMEM; 213 return -ENOMEM;
251 snprintf(kctl->id.name, sizeof(kctl->id.name), "%s Jack", name);
252 kctl->id.index = idx;
253 kctl->private_value = nid;
254 if (snd_hda_ctl_add(codec, nid, kctl) < 0) 214 if (snd_hda_ctl_add(codec, nid, kctl) < 0)
255 return -ENOMEM; 215 return -ENOMEM;
256 jack->kctl = kctl; 216 jack->kctl = kctl;
diff --git a/sound/pci/hda/hda_jack.h b/sound/pci/hda/hda_jack.h
index 69a67f8e4f45..4bb75ee16b56 100644
--- a/sound/pci/hda/hda_jack.h
+++ b/sound/pci/hda/hda_jack.h
@@ -21,7 +21,6 @@ struct hda_jack_tbl {
21 unsigned int pin_sense; /* cached pin-sense value */ 21 unsigned int pin_sense; /* cached pin-sense value */
22 unsigned int jack_detect:1; /* capable of jack-detection? */ 22 unsigned int jack_detect:1; /* capable of jack-detection? */
23 unsigned int jack_dirty:1; /* needs to update? */ 23 unsigned int jack_dirty:1; /* needs to update? */
24 unsigned int need_notify:1; /* to be notified? */
25 struct snd_kcontrol *kctl; /* assigned kctl for jack-detection */ 24 struct snd_kcontrol *kctl; /* assigned kctl for jack-detection */
26}; 25};
27 26