diff options
-rw-r--r-- | include/sound/jack.h | 8 | ||||
-rw-r--r-- | sound/core/jack.c | 71 |
2 files changed, 73 insertions, 6 deletions
diff --git a/include/sound/jack.h b/include/sound/jack.h index f236e426a706..d90b9fa32707 100644 --- a/include/sound/jack.h +++ b/include/sound/jack.h | |||
@@ -42,6 +42,11 @@ enum snd_jack_types { | |||
42 | SND_JACK_MECHANICAL = 0x0008, /* If detected separately */ | 42 | SND_JACK_MECHANICAL = 0x0008, /* If detected separately */ |
43 | SND_JACK_VIDEOOUT = 0x0010, | 43 | SND_JACK_VIDEOOUT = 0x0010, |
44 | SND_JACK_AVOUT = SND_JACK_LINEOUT | SND_JACK_VIDEOOUT, | 44 | SND_JACK_AVOUT = SND_JACK_LINEOUT | SND_JACK_VIDEOOUT, |
45 | |||
46 | /* Kept separate from switches to facilitate implementation */ | ||
47 | SND_JACK_BTN_0 = 0x4000, | ||
48 | SND_JACK_BTN_1 = 0x2000, | ||
49 | SND_JACK_BTN_2 = 0x1000, | ||
45 | }; | 50 | }; |
46 | 51 | ||
47 | struct snd_jack { | 52 | struct snd_jack { |
@@ -50,6 +55,7 @@ struct snd_jack { | |||
50 | int type; | 55 | int type; |
51 | const char *id; | 56 | const char *id; |
52 | char name[100]; | 57 | char name[100]; |
58 | unsigned int key[3]; /* Keep in sync with definitions above */ | ||
53 | void *private_data; | 59 | void *private_data; |
54 | void (*private_free)(struct snd_jack *); | 60 | void (*private_free)(struct snd_jack *); |
55 | }; | 61 | }; |
@@ -59,6 +65,8 @@ struct snd_jack { | |||
59 | int snd_jack_new(struct snd_card *card, const char *id, int type, | 65 | int snd_jack_new(struct snd_card *card, const char *id, int type, |
60 | struct snd_jack **jack); | 66 | struct snd_jack **jack); |
61 | void snd_jack_set_parent(struct snd_jack *jack, struct device *parent); | 67 | void snd_jack_set_parent(struct snd_jack *jack, struct device *parent); |
68 | int snd_jack_set_key(struct snd_jack *jack, enum snd_jack_types type, | ||
69 | int keytype); | ||
62 | 70 | ||
63 | void snd_jack_report(struct snd_jack *jack, int status); | 71 | void snd_jack_report(struct snd_jack *jack, int status); |
64 | 72 | ||
diff --git a/sound/core/jack.c b/sound/core/jack.c index f705eec7372a..3813e7b04d05 100644 --- a/sound/core/jack.c +++ b/sound/core/jack.c | |||
@@ -23,7 +23,7 @@ | |||
23 | #include <sound/jack.h> | 23 | #include <sound/jack.h> |
24 | #include <sound/core.h> | 24 | #include <sound/core.h> |
25 | 25 | ||
26 | static int jack_types[] = { | 26 | static int jack_switch_types[] = { |
27 | SW_HEADPHONE_INSERT, | 27 | SW_HEADPHONE_INSERT, |
28 | SW_MICROPHONE_INSERT, | 28 | SW_MICROPHONE_INSERT, |
29 | SW_LINEOUT_INSERT, | 29 | SW_LINEOUT_INSERT, |
@@ -55,7 +55,7 @@ static int snd_jack_dev_register(struct snd_device *device) | |||
55 | { | 55 | { |
56 | struct snd_jack *jack = device->device_data; | 56 | struct snd_jack *jack = device->device_data; |
57 | struct snd_card *card = device->card; | 57 | struct snd_card *card = device->card; |
58 | int err; | 58 | int err, i; |
59 | 59 | ||
60 | snprintf(jack->name, sizeof(jack->name), "%s %s", | 60 | snprintf(jack->name, sizeof(jack->name), "%s %s", |
61 | card->shortname, jack->id); | 61 | card->shortname, jack->id); |
@@ -65,6 +65,19 @@ static int snd_jack_dev_register(struct snd_device *device) | |||
65 | if (!jack->input_dev->dev.parent) | 65 | if (!jack->input_dev->dev.parent) |
66 | jack->input_dev->dev.parent = snd_card_get_device_link(card); | 66 | jack->input_dev->dev.parent = snd_card_get_device_link(card); |
67 | 67 | ||
68 | /* Add capabilities for any keys that are enabled */ | ||
69 | for (i = 0; i < ARRAY_SIZE(jack->key); i++) { | ||
70 | int testbit = SND_JACK_BTN_0 >> i; | ||
71 | |||
72 | if (!(jack->type & testbit)) | ||
73 | continue; | ||
74 | |||
75 | if (!jack->key[i]) | ||
76 | jack->key[i] = BTN_0 + i; | ||
77 | |||
78 | input_set_capability(jack->input_dev, EV_KEY, jack->key[i]); | ||
79 | } | ||
80 | |||
68 | err = input_register_device(jack->input_dev); | 81 | err = input_register_device(jack->input_dev); |
69 | if (err == 0) | 82 | if (err == 0) |
70 | jack->registered = 1; | 83 | jack->registered = 1; |
@@ -112,10 +125,10 @@ int snd_jack_new(struct snd_card *card, const char *id, int type, | |||
112 | 125 | ||
113 | jack->type = type; | 126 | jack->type = type; |
114 | 127 | ||
115 | for (i = 0; i < ARRAY_SIZE(jack_types); i++) | 128 | for (i = 0; i < ARRAY_SIZE(jack_switch_types); i++) |
116 | if (type & (1 << i)) | 129 | if (type & (1 << i)) |
117 | input_set_capability(jack->input_dev, EV_SW, | 130 | input_set_capability(jack->input_dev, EV_SW, |
118 | jack_types[i]); | 131 | jack_switch_types[i]); |
119 | 132 | ||
120 | err = snd_device_new(card, SNDRV_DEV_JACK, jack, &ops); | 133 | err = snd_device_new(card, SNDRV_DEV_JACK, jack, &ops); |
121 | if (err < 0) | 134 | if (err < 0) |
@@ -151,6 +164,43 @@ void snd_jack_set_parent(struct snd_jack *jack, struct device *parent) | |||
151 | EXPORT_SYMBOL(snd_jack_set_parent); | 164 | EXPORT_SYMBOL(snd_jack_set_parent); |
152 | 165 | ||
153 | /** | 166 | /** |
167 | * snd_jack_set_key - Set a key mapping on a jack | ||
168 | * | ||
169 | * @jack: The jack to configure | ||
170 | * @type: Jack report type for this key | ||
171 | * @keytype: Input layer key type to be reported | ||
172 | * | ||
173 | * Map a SND_JACK_BTN_ button type to an input layer key, allowing | ||
174 | * reporting of keys on accessories via the jack abstraction. If no | ||
175 | * mapping is provided but keys are enabled in the jack type then | ||
176 | * BTN_n numeric buttons will be reported. | ||
177 | * | ||
178 | * Note that this is intended to be use by simple devices with small | ||
179 | * numbers of keys that can be reported. It is also possible to | ||
180 | * access the input device directly - devices with complex input | ||
181 | * capabilities on accessories should consider doing this rather than | ||
182 | * using this abstraction. | ||
183 | * | ||
184 | * This function may only be called prior to registration of the jack. | ||
185 | */ | ||
186 | int snd_jack_set_key(struct snd_jack *jack, enum snd_jack_types type, | ||
187 | int keytype) | ||
188 | { | ||
189 | int key = fls(SND_JACK_BTN_0) - fls(type); | ||
190 | |||
191 | WARN_ON(jack->registered); | ||
192 | |||
193 | if (!keytype || key >= ARRAY_SIZE(jack->key)) | ||
194 | return -EINVAL; | ||
195 | |||
196 | jack->type |= type; | ||
197 | jack->key[key] = keytype; | ||
198 | |||
199 | return 0; | ||
200 | } | ||
201 | EXPORT_SYMBOL(snd_jack_set_key); | ||
202 | |||
203 | /** | ||
154 | * snd_jack_report - Report the current status of a jack | 204 | * snd_jack_report - Report the current status of a jack |
155 | * | 205 | * |
156 | * @jack: The jack to report status for | 206 | * @jack: The jack to report status for |
@@ -163,10 +213,19 @@ void snd_jack_report(struct snd_jack *jack, int status) | |||
163 | if (!jack) | 213 | if (!jack) |
164 | return; | 214 | return; |
165 | 215 | ||
166 | for (i = 0; i < ARRAY_SIZE(jack_types); i++) { | 216 | for (i = 0; i < ARRAY_SIZE(jack->key); i++) { |
217 | int testbit = SND_JACK_BTN_0 >> i; | ||
218 | |||
219 | if (jack->type & testbit) | ||
220 | input_report_key(jack->input_dev, jack->key[i], | ||
221 | status & testbit); | ||
222 | } | ||
223 | |||
224 | for (i = 0; i < ARRAY_SIZE(jack_switch_types); i++) { | ||
167 | int testbit = 1 << i; | 225 | int testbit = 1 << i; |
168 | if (jack->type & testbit) | 226 | if (jack->type & testbit) |
169 | input_report_switch(jack->input_dev, jack_types[i], | 227 | input_report_switch(jack->input_dev, |
228 | jack_switch_types[i], | ||
170 | status & testbit); | 229 | status & testbit); |
171 | } | 230 | } |
172 | 231 | ||