linux/sound/core/jack.c
<<
>>
Prefs
   1/*
   2 *  Jack abstraction layer
   3 *
   4 *  Copyright 2008 Wolfson Microelectronics
   5 *
   6 *   This program is free software; you can redistribute it and/or modify
   7 *   it under the terms of the GNU General Public License as published by
   8 *   the Free Software Foundation; either version 2 of the License, or
   9 *   (at your option) any later version.
  10 *
  11 *   This program is distributed in the hope that it will be useful,
  12 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 *   GNU General Public License for more details.
  15 *
  16 *   You should have received a copy of the GNU General Public License
  17 *   along with this program; if not, write to the Free Software
  18 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  19 *
  20 */
  21
  22#include <linux/input.h>
  23#include <linux/slab.h>
  24#include <linux/module.h>
  25#include <sound/jack.h>
  26#include <sound/core.h>
  27#include <sound/control.h>
  28
  29struct snd_jack_kctl {
  30        struct snd_kcontrol *kctl;
  31        struct list_head list;  /* list of controls belong to the same jack */
  32        unsigned int mask_bits; /* only masked status bits are reported via kctl */
  33};
  34
  35#ifdef CONFIG_SND_JACK_INPUT_DEV
  36static int jack_switch_types[SND_JACK_SWITCH_TYPES] = {
  37        SW_HEADPHONE_INSERT,
  38        SW_MICROPHONE_INSERT,
  39        SW_LINEOUT_INSERT,
  40        SW_JACK_PHYSICAL_INSERT,
  41        SW_VIDEOOUT_INSERT,
  42        SW_LINEIN_INSERT,
  43};
  44#endif /* CONFIG_SND_JACK_INPUT_DEV */
  45
  46static int snd_jack_dev_disconnect(struct snd_device *device)
  47{
  48#ifdef CONFIG_SND_JACK_INPUT_DEV
  49        struct snd_jack *jack = device->device_data;
  50
  51        if (!jack->input_dev)
  52                return 0;
  53
  54        /* If the input device is registered with the input subsystem
  55         * then we need to use a different deallocator. */
  56        if (jack->registered)
  57                input_unregister_device(jack->input_dev);
  58        else
  59                input_free_device(jack->input_dev);
  60        jack->input_dev = NULL;
  61#endif /* CONFIG_SND_JACK_INPUT_DEV */
  62        return 0;
  63}
  64
  65static int snd_jack_dev_free(struct snd_device *device)
  66{
  67        struct snd_jack *jack = device->device_data;
  68        struct snd_card *card = device->card;
  69        struct snd_jack_kctl *jack_kctl, *tmp_jack_kctl;
  70
  71        list_for_each_entry_safe(jack_kctl, tmp_jack_kctl, &jack->kctl_list, list) {
  72                list_del_init(&jack_kctl->list);
  73                snd_ctl_remove(card, jack_kctl->kctl);
  74        }
  75        if (jack->private_free)
  76                jack->private_free(jack);
  77
  78        snd_jack_dev_disconnect(device);
  79
  80        kfree(jack->id);
  81        kfree(jack);
  82
  83        return 0;
  84}
  85
  86#ifdef CONFIG_SND_JACK_INPUT_DEV
  87static int snd_jack_dev_register(struct snd_device *device)
  88{
  89        struct snd_jack *jack = device->device_data;
  90        struct snd_card *card = device->card;
  91        int err, i;
  92
  93        snprintf(jack->name, sizeof(jack->name), "%s %s",
  94                 card->shortname, jack->id);
  95
  96        if (!jack->input_dev)
  97                return 0;
  98
  99        jack->input_dev->name = jack->name;
 100
 101        /* Default to the sound card device. */
 102        if (!jack->input_dev->dev.parent)
 103                jack->input_dev->dev.parent = snd_card_get_device_link(card);
 104
 105        /* Add capabilities for any keys that are enabled */
 106        for (i = 0; i < ARRAY_SIZE(jack->key); i++) {
 107                int testbit = SND_JACK_BTN_0 >> i;
 108
 109                if (!(jack->type & testbit))
 110                        continue;
 111
 112                if (!jack->key[i])
 113                        jack->key[i] = BTN_0 + i;
 114
 115                input_set_capability(jack->input_dev, EV_KEY, jack->key[i]);
 116        }
 117
 118        err = input_register_device(jack->input_dev);
 119        if (err == 0)
 120                jack->registered = 1;
 121
 122        return err;
 123}
 124#endif /* CONFIG_SND_JACK_INPUT_DEV */
 125
 126static void snd_jack_kctl_private_free(struct snd_kcontrol *kctl)
 127{
 128        struct snd_jack_kctl *jack_kctl;
 129
 130        jack_kctl = kctl->private_data;
 131        if (jack_kctl) {
 132                list_del(&jack_kctl->list);
 133                kfree(jack_kctl);
 134        }
 135}
 136
 137static void snd_jack_kctl_add(struct snd_jack *jack, struct snd_jack_kctl *jack_kctl)
 138{
 139        list_add_tail(&jack_kctl->list, &jack->kctl_list);
 140}
 141
 142static struct snd_jack_kctl * snd_jack_kctl_new(struct snd_card *card, const char *name, unsigned int mask)
 143{
 144        struct snd_kcontrol *kctl;
 145        struct snd_jack_kctl *jack_kctl;
 146        int err;
 147
 148        kctl = snd_kctl_jack_new(name, card);
 149        if (!kctl)
 150                return NULL;
 151
 152        err = snd_ctl_add(card, kctl);
 153        if (err < 0)
 154                return NULL;
 155
 156        jack_kctl = kzalloc(sizeof(*jack_kctl), GFP_KERNEL);
 157
 158        if (!jack_kctl)
 159                goto error;
 160
 161        jack_kctl->kctl = kctl;
 162        jack_kctl->mask_bits = mask;
 163
 164        kctl->private_data = jack_kctl;
 165        kctl->private_free = snd_jack_kctl_private_free;
 166
 167        return jack_kctl;
 168error:
 169        snd_ctl_free_one(kctl);
 170        return NULL;
 171}
 172
 173/**
 174 * snd_jack_add_new_kctl - Create a new snd_jack_kctl and add it to jack
 175 * @jack:  the jack instance which the kctl will attaching to
 176 * @name:  the name for the snd_kcontrol object
 177 * @mask:  a bitmask of enum snd_jack_type values that can be detected
 178 *         by this snd_jack_kctl object.
 179 *
 180 * Creates a new snd_kcontrol object and adds it to the jack kctl_list.
 181 *
 182 * Return: Zero if successful, or a negative error code on failure.
 183 */
 184int snd_jack_add_new_kctl(struct snd_jack *jack, const char * name, int mask)
 185{
 186        struct snd_jack_kctl *jack_kctl;
 187
 188        jack_kctl = snd_jack_kctl_new(jack->card, name, mask);
 189        if (!jack_kctl)
 190                return -ENOMEM;
 191
 192        snd_jack_kctl_add(jack, jack_kctl);
 193        return 0;
 194}
 195EXPORT_SYMBOL(snd_jack_add_new_kctl);
 196
 197/**
 198 * snd_jack_new - Create a new jack
 199 * @card:  the card instance
 200 * @id:    an identifying string for this jack
 201 * @type:  a bitmask of enum snd_jack_type values that can be detected by
 202 *         this jack
 203 * @jjack: Used to provide the allocated jack object to the caller.
 204 * @initial_kctl: if true, create a kcontrol and add it to the jack list.
 205 * @phantom_jack: Don't create a input device for phantom jacks.
 206 *
 207 * Creates a new jack object.
 208 *
 209 * Return: Zero if successful, or a negative error code on failure.
 210 * On success @jjack will be initialised.
 211 */
 212int snd_jack_new(struct snd_card *card, const char *id, int type,
 213                 struct snd_jack **jjack, bool initial_kctl, bool phantom_jack)
 214{
 215        struct snd_jack *jack;
 216        struct snd_jack_kctl *jack_kctl = NULL;
 217        int err;
 218        static struct snd_device_ops ops = {
 219                .dev_free = snd_jack_dev_free,
 220#ifdef CONFIG_SND_JACK_INPUT_DEV
 221                .dev_register = snd_jack_dev_register,
 222                .dev_disconnect = snd_jack_dev_disconnect,
 223#endif /* CONFIG_SND_JACK_INPUT_DEV */
 224        };
 225
 226        if (initial_kctl) {
 227                jack_kctl = snd_jack_kctl_new(card, id, type);
 228                if (!jack_kctl)
 229                        return -ENOMEM;
 230        }
 231
 232        jack = kzalloc(sizeof(struct snd_jack), GFP_KERNEL);
 233        if (jack == NULL)
 234                return -ENOMEM;
 235
 236        jack->id = kstrdup(id, GFP_KERNEL);
 237
 238        /* don't creat input device for phantom jack */
 239        if (!phantom_jack) {
 240#ifdef CONFIG_SND_JACK_INPUT_DEV
 241                int i;
 242
 243                jack->input_dev = input_allocate_device();
 244                if (jack->input_dev == NULL) {
 245                        err = -ENOMEM;
 246                        goto fail_input;
 247                }
 248
 249                jack->input_dev->phys = "ALSA";
 250
 251                jack->type = type;
 252
 253                for (i = 0; i < SND_JACK_SWITCH_TYPES; i++)
 254                        if (type & (1 << i))
 255                                input_set_capability(jack->input_dev, EV_SW,
 256                                                     jack_switch_types[i]);
 257
 258#endif /* CONFIG_SND_JACK_INPUT_DEV */
 259        }
 260
 261        err = snd_device_new(card, SNDRV_DEV_JACK, jack, &ops);
 262        if (err < 0)
 263                goto fail_input;
 264
 265        jack->card = card;
 266        INIT_LIST_HEAD(&jack->kctl_list);
 267
 268        if (initial_kctl)
 269                snd_jack_kctl_add(jack, jack_kctl);
 270
 271        *jjack = jack;
 272
 273        return 0;
 274
 275fail_input:
 276#ifdef CONFIG_SND_JACK_INPUT_DEV
 277        input_free_device(jack->input_dev);
 278#endif
 279        kfree(jack->id);
 280        kfree(jack);
 281        return err;
 282}
 283EXPORT_SYMBOL(snd_jack_new);
 284
 285#ifdef CONFIG_SND_JACK_INPUT_DEV
 286/**
 287 * snd_jack_set_parent - Set the parent device for a jack
 288 *
 289 * @jack:   The jack to configure
 290 * @parent: The device to set as parent for the jack.
 291 *
 292 * Set the parent for the jack devices in the device tree.  This
 293 * function is only valid prior to registration of the jack.  If no
 294 * parent is configured then the parent device will be the sound card.
 295 */
 296void snd_jack_set_parent(struct snd_jack *jack, struct device *parent)
 297{
 298        WARN_ON(jack->registered);
 299        if (!jack->input_dev)
 300                return;
 301
 302        jack->input_dev->dev.parent = parent;
 303}
 304EXPORT_SYMBOL(snd_jack_set_parent);
 305
 306/**
 307 * snd_jack_set_key - Set a key mapping on a jack
 308 *
 309 * @jack:    The jack to configure
 310 * @type:    Jack report type for this key
 311 * @keytype: Input layer key type to be reported
 312 *
 313 * Map a SND_JACK_BTN_ button type to an input layer key, allowing
 314 * reporting of keys on accessories via the jack abstraction.  If no
 315 * mapping is provided but keys are enabled in the jack type then
 316 * BTN_n numeric buttons will be reported.
 317 *
 318 * If jacks are not reporting via the input API this call will have no
 319 * effect.
 320 *
 321 * Note that this is intended to be use by simple devices with small
 322 * numbers of keys that can be reported.  It is also possible to
 323 * access the input device directly - devices with complex input
 324 * capabilities on accessories should consider doing this rather than
 325 * using this abstraction.
 326 *
 327 * This function may only be called prior to registration of the jack.
 328 *
 329 * Return: Zero if successful, or a negative error code on failure.
 330 */
 331int snd_jack_set_key(struct snd_jack *jack, enum snd_jack_types type,
 332                     int keytype)
 333{
 334        int key = fls(SND_JACK_BTN_0) - fls(type);
 335
 336        WARN_ON(jack->registered);
 337
 338        if (!keytype || key >= ARRAY_SIZE(jack->key))
 339                return -EINVAL;
 340
 341        jack->type |= type;
 342        jack->key[key] = keytype;
 343        return 0;
 344}
 345EXPORT_SYMBOL(snd_jack_set_key);
 346#endif /* CONFIG_SND_JACK_INPUT_DEV */
 347
 348/**
 349 * snd_jack_report - Report the current status of a jack
 350 *
 351 * @jack:   The jack to report status for
 352 * @status: The current status of the jack
 353 */
 354void snd_jack_report(struct snd_jack *jack, int status)
 355{
 356        struct snd_jack_kctl *jack_kctl;
 357#ifdef CONFIG_SND_JACK_INPUT_DEV
 358        int i;
 359#endif
 360
 361        if (!jack)
 362                return;
 363
 364        list_for_each_entry(jack_kctl, &jack->kctl_list, list)
 365                snd_kctl_jack_report(jack->card, jack_kctl->kctl,
 366                                            status & jack_kctl->mask_bits);
 367
 368#ifdef CONFIG_SND_JACK_INPUT_DEV
 369        if (!jack->input_dev)
 370                return;
 371
 372        for (i = 0; i < ARRAY_SIZE(jack->key); i++) {
 373                int testbit = SND_JACK_BTN_0 >> i;
 374
 375                if (jack->type & testbit)
 376                        input_report_key(jack->input_dev, jack->key[i],
 377                                         status & testbit);
 378        }
 379
 380        for (i = 0; i < ARRAY_SIZE(jack_switch_types); i++) {
 381                int testbit = 1 << i;
 382                if (jack->type & testbit)
 383                        input_report_switch(jack->input_dev,
 384                                            jack_switch_types[i],
 385                                            status & testbit);
 386        }
 387
 388        input_sync(jack->input_dev);
 389#endif /* CONFIG_SND_JACK_INPUT_DEV */
 390}
 391EXPORT_SYMBOL(snd_jack_report);
 392