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 14b8a4ee690d..4902ae568730 100644 --- a/sound/core/jack.c +++ b/sound/core/jack.c | |||
| @@ -24,7 +24,7 @@ | |||
| 24 | #include <sound/jack.h> | 24 | #include <sound/jack.h> |
| 25 | #include <sound/core.h> | 25 | #include <sound/core.h> |
| 26 | 26 | ||
| 27 | static int jack_types[] = { | 27 | static int jack_switch_types[] = { |
| 28 | SW_HEADPHONE_INSERT, | 28 | SW_HEADPHONE_INSERT, |
| 29 | SW_MICROPHONE_INSERT, | 29 | SW_MICROPHONE_INSERT, |
| 30 | SW_LINEOUT_INSERT, | 30 | SW_LINEOUT_INSERT, |
| @@ -56,7 +56,7 @@ static int snd_jack_dev_register(struct snd_device *device) | |||
| 56 | { | 56 | { |
| 57 | struct snd_jack *jack = device->device_data; | 57 | struct snd_jack *jack = device->device_data; |
| 58 | struct snd_card *card = device->card; | 58 | struct snd_card *card = device->card; |
| 59 | int err; | 59 | int err, i; |
| 60 | 60 | ||
| 61 | snprintf(jack->name, sizeof(jack->name), "%s %s", | 61 | snprintf(jack->name, sizeof(jack->name), "%s %s", |
| 62 | card->shortname, jack->id); | 62 | card->shortname, jack->id); |
| @@ -66,6 +66,19 @@ static int snd_jack_dev_register(struct snd_device *device) | |||
| 66 | if (!jack->input_dev->dev.parent) | 66 | if (!jack->input_dev->dev.parent) |
| 67 | jack->input_dev->dev.parent = snd_card_get_device_link(card); | 67 | jack->input_dev->dev.parent = snd_card_get_device_link(card); |
| 68 | 68 | ||
| 69 | /* Add capabilities for any keys that are enabled */ | ||
| 70 | for (i = 0; i < ARRAY_SIZE(jack->key); i++) { | ||
| 71 | int testbit = SND_JACK_BTN_0 >> i; | ||
| 72 | |||
| 73 | if (!(jack->type & testbit)) | ||
| 74 | continue; | ||
| 75 | |||
| 76 | if (!jack->key[i]) | ||
| 77 | jack->key[i] = BTN_0 + i; | ||
| 78 | |||
| 79 | input_set_capability(jack->input_dev, EV_KEY, jack->key[i]); | ||
| 80 | } | ||
| 81 | |||
| 69 | err = input_register_device(jack->input_dev); | 82 | err = input_register_device(jack->input_dev); |
| 70 | if (err == 0) | 83 | if (err == 0) |
| 71 | jack->registered = 1; | 84 | jack->registered = 1; |
| @@ -113,10 +126,10 @@ int snd_jack_new(struct snd_card *card, const char *id, int type, | |||
| 113 | 126 | ||
| 114 | jack->type = type; | 127 | jack->type = type; |
| 115 | 128 | ||
| 116 | for (i = 0; i < ARRAY_SIZE(jack_types); i++) | 129 | for (i = 0; i < ARRAY_SIZE(jack_switch_types); i++) |
| 117 | if (type & (1 << i)) | 130 | if (type & (1 << i)) |
| 118 | input_set_capability(jack->input_dev, EV_SW, | 131 | input_set_capability(jack->input_dev, EV_SW, |
| 119 | jack_types[i]); | 132 | jack_switch_types[i]); |
| 120 | 133 | ||
| 121 | err = snd_device_new(card, SNDRV_DEV_JACK, jack, &ops); | 134 | err = snd_device_new(card, SNDRV_DEV_JACK, jack, &ops); |
| 122 | if (err < 0) | 135 | if (err < 0) |
| @@ -152,6 +165,43 @@ void snd_jack_set_parent(struct snd_jack *jack, struct device *parent) | |||
| 152 | EXPORT_SYMBOL(snd_jack_set_parent); | 165 | EXPORT_SYMBOL(snd_jack_set_parent); |
| 153 | 166 | ||
| 154 | /** | 167 | /** |
| 168 | * snd_jack_set_key - Set a key mapping on a jack | ||
| 169 | * | ||
| 170 | * @jack: The jack to configure | ||
| 171 | * @type: Jack report type for this key | ||
| 172 | * @keytype: Input layer key type to be reported | ||
| 173 | * | ||
| 174 | * Map a SND_JACK_BTN_ button type to an input layer key, allowing | ||
| 175 | * reporting of keys on accessories via the jack abstraction. If no | ||
| 176 | * mapping is provided but keys are enabled in the jack type then | ||
| 177 | * BTN_n numeric buttons will be reported. | ||
| 178 | * | ||
| 179 | * Note that this is intended to be use by simple devices with small | ||
| 180 | * numbers of keys that can be reported. It is also possible to | ||
| 181 | * access the input device directly - devices with complex input | ||
| 182 | * capabilities on accessories should consider doing this rather than | ||
| 183 | * using this abstraction. | ||
| 184 | * | ||
| 185 | * This function may only be called prior to registration of the jack. | ||
| 186 | */ | ||
| 187 | int snd_jack_set_key(struct snd_jack *jack, enum snd_jack_types type, | ||
| 188 | int keytype) | ||
| 189 | { | ||
| 190 | int key = fls(SND_JACK_BTN_0) - fls(type); | ||
| 191 | |||
| 192 | WARN_ON(jack->registered); | ||
| 193 | |||
| 194 | if (!keytype || key >= ARRAY_SIZE(jack->key)) | ||
| 195 | return -EINVAL; | ||
| 196 | |||
| 197 | jack->type |= type; | ||
| 198 | jack->key[key] = keytype; | ||
| 199 | |||
| 200 | return 0; | ||
| 201 | } | ||
| 202 | EXPORT_SYMBOL(snd_jack_set_key); | ||
| 203 | |||
| 204 | /** | ||
| 155 | * snd_jack_report - Report the current status of a jack | 205 | * snd_jack_report - Report the current status of a jack |
| 156 | * | 206 | * |
| 157 | * @jack: The jack to report status for | 207 | * @jack: The jack to report status for |
| @@ -164,10 +214,19 @@ void snd_jack_report(struct snd_jack *jack, int status) | |||
| 164 | if (!jack) | 214 | if (!jack) |
| 165 | return; | 215 | return; |
| 166 | 216 | ||
| 167 | for (i = 0; i < ARRAY_SIZE(jack_types); i++) { | 217 | for (i = 0; i < ARRAY_SIZE(jack->key); i++) { |
| 218 | int testbit = SND_JACK_BTN_0 >> i; | ||
| 219 | |||
| 220 | if (jack->type & testbit) | ||
| 221 | input_report_key(jack->input_dev, jack->key[i], | ||
| 222 | status & testbit); | ||
| 223 | } | ||
| 224 | |||
| 225 | for (i = 0; i < ARRAY_SIZE(jack_switch_types); i++) { | ||
| 168 | int testbit = 1 << i; | 226 | int testbit = 1 << i; |
| 169 | if (jack->type & testbit) | 227 | if (jack->type & testbit) |
| 170 | input_report_switch(jack->input_dev, jack_types[i], | 228 | input_report_switch(jack->input_dev, |
| 229 | jack_switch_types[i], | ||
| 171 | status & testbit); | 230 | status & testbit); |
| 172 | } | 231 | } |
| 173 | 232 | ||
