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