Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/livep...
[cascardo/linux.git] / drivers / extcon / extcon.c
index f209a69..7829846 100644 (file)
@@ -93,6 +93,11 @@ struct __extcon_info {
                .id = EXTCON_CHG_USB_SLOW,
                .name = "SLOW-CHARGER",
        },
+       [EXTCON_CHG_WPT] = {
+               .type = EXTCON_TYPE_CHG,
+               .id = EXTCON_CHG_WPT,
+               .name = "WPT",
+       },
 
        /* Jack external connector */
        [EXTCON_JACK_MICROPHONE] = {
@@ -157,6 +162,16 @@ struct __extcon_info {
                .id = EXTCON_DISP_VGA,
                .name = "VGA",
        },
+       [EXTCON_DISP_DP] = {
+               .type = EXTCON_TYPE_DISP | EXTCON_TYPE_USB,
+               .id = EXTCON_DISP_DP,
+               .name = "DP",
+       },
+       [EXTCON_DISP_HMD] = {
+               .type = EXTCON_TYPE_DISP | EXTCON_TYPE_USB,
+               .id = EXTCON_DISP_HMD,
+               .name = "HMD",
+       },
 
        /* Miscellaneous external connector */
        [EXTCON_DOCK] = {
@@ -196,6 +211,16 @@ struct extcon_cable {
        struct device_attribute attr_state;
 
        struct attribute *attrs[3]; /* to be fed to attr_g.attrs */
+
+       union extcon_property_value usb_propval[EXTCON_PROP_USB_CNT];
+       union extcon_property_value chg_propval[EXTCON_PROP_CHG_CNT];
+       union extcon_property_value jack_propval[EXTCON_PROP_JACK_CNT];
+       union extcon_property_value disp_propval[EXTCON_PROP_DISP_CNT];
+
+       unsigned long usb_bits[BITS_TO_LONGS(EXTCON_PROP_USB_CNT)];
+       unsigned long chg_bits[BITS_TO_LONGS(EXTCON_PROP_CHG_CNT)];
+       unsigned long jack_bits[BITS_TO_LONGS(EXTCON_PROP_JACK_CNT)];
+       unsigned long disp_bits[BITS_TO_LONGS(EXTCON_PROP_DISP_CNT)];
 };
 
 static struct class *extcon_class;
@@ -248,14 +273,93 @@ static int find_cable_index_by_id(struct extcon_dev *edev, const unsigned int id
        return -EINVAL;
 }
 
-static bool is_extcon_changed(u32 prev, u32 new, int idx, bool *attached)
+static int get_extcon_type(unsigned int prop)
+{
+       switch (prop) {
+       case EXTCON_PROP_USB_MIN ... EXTCON_PROP_USB_MAX:
+               return EXTCON_TYPE_USB;
+       case EXTCON_PROP_CHG_MIN ... EXTCON_PROP_CHG_MAX:
+               return EXTCON_TYPE_CHG;
+       case EXTCON_PROP_JACK_MIN ... EXTCON_PROP_JACK_MAX:
+               return EXTCON_TYPE_JACK;
+       case EXTCON_PROP_DISP_MIN ... EXTCON_PROP_DISP_MAX:
+               return EXTCON_TYPE_DISP;
+       default:
+               return -EINVAL;
+       }
+}
+
+static bool is_extcon_attached(struct extcon_dev *edev, unsigned int index)
+{
+       return !!(edev->state & BIT(index));
+}
+
+static bool is_extcon_changed(struct extcon_dev *edev, int index,
+                               bool new_state)
 {
-       if (((prev >> idx) & 0x1) != ((new >> idx) & 0x1)) {
-               *attached = ((new >> idx) & 0x1) ? true : false;
-               return true;
+       int state = !!(edev->state & BIT(index));
+       return (state != new_state);
+}
+
+static bool is_extcon_property_supported(unsigned int id, unsigned int prop)
+{
+       int type;
+
+       /* Check whether the property is supported or not. */
+       type = get_extcon_type(prop);
+       if (type < 0)
+               return false;
+
+       /* Check whether a specific extcon id supports the property or not. */
+       return !!(extcon_info[id].type & type);
+}
+
+static int is_extcon_property_capability(struct extcon_dev *edev,
+                               unsigned int id, int index,unsigned int prop)
+{
+       struct extcon_cable *cable;
+       int type, ret;
+
+       /* Check whether the property is supported or not. */
+       type = get_extcon_type(prop);
+       if (type < 0)
+               return type;
+
+       cable = &edev->cables[index];
+
+       switch (type) {
+       case EXTCON_TYPE_USB:
+               ret = test_bit(prop - EXTCON_PROP_USB_MIN, cable->usb_bits);
+               break;
+       case EXTCON_TYPE_CHG:
+               ret = test_bit(prop - EXTCON_PROP_CHG_MIN, cable->chg_bits);
+               break;
+       case EXTCON_TYPE_JACK:
+               ret = test_bit(prop - EXTCON_PROP_JACK_MIN, cable->jack_bits);
+               break;
+       case EXTCON_TYPE_DISP:
+               ret = test_bit(prop - EXTCON_PROP_DISP_MIN, cable->disp_bits);
+               break;
+       default:
+               ret = -EINVAL;
        }
 
-       return false;
+       return ret;
+}
+
+static void init_property(struct extcon_dev *edev, unsigned int id, int index)
+{
+       unsigned int type = extcon_info[id].type;
+       struct extcon_cable *cable = &edev->cables[index];
+
+       if (EXTCON_TYPE_USB & type)
+               memset(cable->usb_propval, 0, sizeof(cable->usb_propval));
+       if (EXTCON_TYPE_CHG & type)
+               memset(cable->chg_propval, 0, sizeof(cable->chg_propval));
+       if (EXTCON_TYPE_JACK & type)
+               memset(cable->jack_propval, 0, sizeof(cable->jack_propval));
+       if (EXTCON_TYPE_DISP & type)
+               memset(cable->disp_propval, 0, sizeof(cable->disp_propval));
 }
 
 static ssize_t state_show(struct device *dev, struct device_attribute *attr,
@@ -306,26 +410,17 @@ static ssize_t cable_state_show(struct device *dev,
        int i = cable->cable_index;
 
        return sprintf(buf, "%d\n",
-                      extcon_get_cable_state_(cable->edev,
-                                              cable->edev->supported_cable[i]));
+               extcon_get_state(cable->edev, cable->edev->supported_cable[i]));
 }
 
 /**
- * extcon_update_state() - Update the cable attach states of the extcon device
- *                        only for the masked bits.
- * @edev:      the extcon device
- * @mask:      the bit mask to designate updated bits.
- * @state:     new cable attach status for @edev
- *
- * Changing the state sends uevent with environment variable containing
- * the name of extcon device (envp[0]) and the state output (envp[1]).
- * Tizen uses this format for extcon device to get events from ports.
- * Android uses this format as well.
+ * extcon_sync()       - Synchronize the states for both the attached/detached
+ * @edev:              the extcon device that has the cable.
  *
- * Note that the notifier provides which bits are changed in the state
- * variable with the val parameter (second) to the callback.
+ * This function send a notification to synchronize the all states of a
+ * specific external connector
  */
-static int extcon_update_state(struct extcon_dev *edev, u32 mask, u32 state)
+int extcon_sync(struct extcon_dev *edev, unsigned int id)
 {
        char name_buf[120];
        char state_buf[120];
@@ -334,82 +429,68 @@ static int extcon_update_state(struct extcon_dev *edev, u32 mask, u32 state)
        int env_offset = 0;
        int length;
        int index;
+       int state;
        unsigned long flags;
-       bool attached;
 
        if (!edev)
                return -EINVAL;
 
+       index = find_cable_index_by_id(edev, id);
+       if (index < 0)
+               return index;
+
        spin_lock_irqsave(&edev->lock, flags);
 
-       if (edev->state != ((edev->state & ~mask) | (state & mask))) {
-               u32 old_state;
+       state = !!(edev->state & BIT(index));
+       raw_notifier_call_chain(&edev->nh[index], state, edev);
 
-               if (check_mutually_exclusive(edev, (edev->state & ~mask) |
-                                                  (state & mask))) {
-                       spin_unlock_irqrestore(&edev->lock, flags);
-                       return -EPERM;
-               }
-
-               old_state = edev->state;
-               edev->state &= ~mask;
-               edev->state |= state & mask;
+       /* This could be in interrupt handler */
+       prop_buf = (char *)get_zeroed_page(GFP_ATOMIC);
+       if (!prop_buf) {
+               /* Unlock early before uevent */
+               spin_unlock_irqrestore(&edev->lock, flags);
 
-               for (index = 0; index < edev->max_supported; index++) {
-                       if (is_extcon_changed(old_state, edev->state, index,
-                                             &attached))
-                               raw_notifier_call_chain(&edev->nh[index],
-                                                       attached, edev);
-               }
+               dev_err(&edev->dev, "out of memory in extcon_set_state\n");
+               kobject_uevent(&edev->dev.kobj, KOBJ_CHANGE);
 
-               /* This could be in interrupt handler */
-               prop_buf = (char *)get_zeroed_page(GFP_ATOMIC);
-               if (prop_buf) {
-                       length = name_show(&edev->dev, NULL, prop_buf);
-                       if (length > 0) {
-                               if (prop_buf[length - 1] == '\n')
-                                       prop_buf[length - 1] = 0;
-                               snprintf(name_buf, sizeof(name_buf),
-                                       "NAME=%s", prop_buf);
-                               envp[env_offset++] = name_buf;
-                       }
-                       length = state_show(&edev->dev, NULL, prop_buf);
-                       if (length > 0) {
-                               if (prop_buf[length - 1] == '\n')
-                                       prop_buf[length - 1] = 0;
-                               snprintf(state_buf, sizeof(state_buf),
-                                       "STATE=%s", prop_buf);
-                               envp[env_offset++] = state_buf;
-                       }
-                       envp[env_offset] = NULL;
-                       /* Unlock early before uevent */
-                       spin_unlock_irqrestore(&edev->lock, flags);
+               return 0;
+       }
 
-                       kobject_uevent_env(&edev->dev.kobj, KOBJ_CHANGE, envp);
-                       free_page((unsigned long)prop_buf);
-               } else {
-                       /* Unlock early before uevent */
-                       spin_unlock_irqrestore(&edev->lock, flags);
+       length = name_show(&edev->dev, NULL, prop_buf);
+       if (length > 0) {
+               if (prop_buf[length - 1] == '\n')
+                       prop_buf[length - 1] = 0;
+               snprintf(name_buf, sizeof(name_buf), "NAME=%s", prop_buf);
+               envp[env_offset++] = name_buf;
+       }
 
-                       dev_err(&edev->dev, "out of memory in extcon_set_state\n");
-                       kobject_uevent(&edev->dev.kobj, KOBJ_CHANGE);
-               }
-       } else {
-               /* No changes */
-               spin_unlock_irqrestore(&edev->lock, flags);
+       length = state_show(&edev->dev, NULL, prop_buf);
+       if (length > 0) {
+               if (prop_buf[length - 1] == '\n')
+                       prop_buf[length - 1] = 0;
+               snprintf(state_buf, sizeof(state_buf), "STATE=%s", prop_buf);
+               envp[env_offset++] = state_buf;
        }
+       envp[env_offset] = NULL;
+
+       /* Unlock early before uevent */
+       spin_unlock_irqrestore(&edev->lock, flags);
+       kobject_uevent_env(&edev->dev.kobj, KOBJ_CHANGE, envp);
+       free_page((unsigned long)prop_buf);
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(extcon_sync);
 
 /**
- * extcon_get_cable_state_() - Get the status of a specific cable.
+ * extcon_get_state() - Get the state of a external connector.
  * @edev:      the extcon device that has the cable.
  * @id:                the unique id of each external connector in extcon enumeration.
  */
-int extcon_get_cable_state_(struct extcon_dev *edev, const unsigned int id)
+int extcon_get_state(struct extcon_dev *edev, const unsigned int id)
 {
-       int index;
+       int index, state;
+       unsigned long flags;
 
        if (!edev)
                return -EINVAL;
@@ -418,41 +499,372 @@ int extcon_get_cable_state_(struct extcon_dev *edev, const unsigned int id)
        if (index < 0)
                return index;
 
-       if (edev->max_supported && edev->max_supported <= index)
+       spin_lock_irqsave(&edev->lock, flags);
+       state = is_extcon_attached(edev, index);
+       spin_unlock_irqrestore(&edev->lock, flags);
+
+       return state;
+}
+EXPORT_SYMBOL_GPL(extcon_get_state);
+
+/**
+ * extcon_set_state() - Set the state of a external connector.
+ *                     without a notification.
+ * @edev:              the extcon device that has the cable.
+ * @id:                        the unique id of each external connector
+ *                     in extcon enumeration.
+ * @state:             the new cable status. The default semantics is
+ *                     true: attached / false: detached.
+ *
+ * This function only set the state of a external connector without
+ * a notification. To synchronize the data of a external connector,
+ * use extcon_set_state_sync() and extcon_sync().
+ */
+int extcon_set_state(struct extcon_dev *edev, unsigned int id,
+                               bool cable_state)
+{
+       unsigned long flags;
+       int index, ret = 0;
+
+       if (!edev)
                return -EINVAL;
 
-       return !!(edev->state & (1 << index));
+       index = find_cable_index_by_id(edev, id);
+       if (index < 0)
+               return index;
+
+       spin_lock_irqsave(&edev->lock, flags);
+
+       /* Check whether the external connector's state is changed. */
+       if (!is_extcon_changed(edev, index, cable_state))
+               goto out;
+
+       if (check_mutually_exclusive(edev,
+               (edev->state & ~BIT(index)) | (cable_state & BIT(index)))) {
+               ret = -EPERM;
+               goto out;
+       }
+
+       /*
+        * Initialize the value of extcon property before setting
+        * the detached state for an external connector.
+        */
+       if (!cable_state)
+               init_property(edev, id, index);
+
+       /* Update the state for a external connector. */
+       if (cable_state)
+               edev->state |= BIT(index);
+       else
+               edev->state &= ~(BIT(index));
+out:
+       spin_unlock_irqrestore(&edev->lock, flags);
+
+       return ret;
 }
-EXPORT_SYMBOL_GPL(extcon_get_cable_state_);
+EXPORT_SYMBOL_GPL(extcon_set_state);
 
 /**
- * extcon_set_cable_state_() - Set the status of a specific cable.
+ * extcon_set_state_sync() - Set the state of a external connector
+ *                     with a notification.
  * @edev:              the extcon device that has the cable.
  * @id:                        the unique id of each external connector
  *                     in extcon enumeration.
  * @state:             the new cable status. The default semantics is
  *                     true: attached / false: detached.
+ *
+ * This function set the state of external connector and synchronize the data
+ * by usning a notification.
  */
-int extcon_set_cable_state_(struct extcon_dev *edev, unsigned int id,
+int extcon_set_state_sync(struct extcon_dev *edev, unsigned int id,
                                bool cable_state)
 {
-       u32 state;
+       int ret, index;
+       unsigned long flags;
+
+       index = find_cable_index_by_id(edev, id);
+       if (index < 0)
+               return index;
+
+       /* Check whether the external connector's state is changed. */
+       spin_lock_irqsave(&edev->lock, flags);
+       ret = is_extcon_changed(edev, index, cable_state);
+       spin_unlock_irqrestore(&edev->lock, flags);
+       if (!ret)
+               return 0;
+
+       ret = extcon_set_state(edev, id, cable_state);
+       if (ret < 0)
+               return ret;
+
+       return extcon_sync(edev, id);
+}
+EXPORT_SYMBOL_GPL(extcon_set_state_sync);
+
+/**
+ * extcon_get_property() - Get the property value of a specific cable.
+ * @edev:              the extcon device that has the cable.
+ * @id:                        the unique id of each external connector
+ *                     in extcon enumeration.
+ * @prop:              the property id among enum extcon_property.
+ * @prop_val:          the pointer which store the value of property.
+ *
+ * When getting the property value of external connector, the external connector
+ * should be attached. If detached state, function just return 0 without
+ * property value. Also, the each property should be included in the list of
+ * supported properties according to the type of external connectors.
+ *
+ * Returns 0 if success or error number if fail
+ */
+int extcon_get_property(struct extcon_dev *edev, unsigned int id,
+                               unsigned int prop,
+                               union extcon_property_value *prop_val)
+{
+       struct extcon_cable *cable;
+       unsigned long flags;
+       int index, ret = 0;
+
+       *prop_val = (union extcon_property_value)(0);
+
+       if (!edev)
+               return -EINVAL;
+
+       /* Check whether the property is supported or not */
+       if (!is_extcon_property_supported(id, prop))
+               return -EINVAL;
+
+       /* Find the cable index of external connector by using id */
+       index = find_cable_index_by_id(edev, id);
+       if (index < 0)
+               return index;
+
+       spin_lock_irqsave(&edev->lock, flags);
+
+       /* Check whether the property is available or not. */
+       if (!is_extcon_property_capability(edev, id, index, prop)) {
+               spin_unlock_irqrestore(&edev->lock, flags);
+               return -EPERM;
+       }
+
+       /*
+        * Check whether the external connector is attached.
+        * If external connector is detached, the user can not
+        * get the property value.
+        */
+       if (!is_extcon_attached(edev, index)) {
+               spin_unlock_irqrestore(&edev->lock, flags);
+               return 0;
+       }
+
+       cable = &edev->cables[index];
+
+       /* Get the property value according to extcon type */
+       switch (prop) {
+       case EXTCON_PROP_USB_MIN ... EXTCON_PROP_USB_MAX:
+               *prop_val = cable->usb_propval[prop - EXTCON_PROP_USB_MIN];
+               break;
+       case EXTCON_PROP_CHG_MIN ... EXTCON_PROP_CHG_MAX:
+               *prop_val = cable->chg_propval[prop - EXTCON_PROP_CHG_MIN];
+               break;
+       case EXTCON_PROP_JACK_MIN ... EXTCON_PROP_JACK_MAX:
+               *prop_val = cable->jack_propval[prop - EXTCON_PROP_JACK_MIN];
+               break;
+       case EXTCON_PROP_DISP_MIN ... EXTCON_PROP_DISP_MAX:
+               *prop_val = cable->disp_propval[prop - EXTCON_PROP_DISP_MIN];
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+
+       spin_unlock_irqrestore(&edev->lock, flags);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(extcon_get_property);
+
+/**
+ * extcon_set_property() - Set the property value of a specific cable.
+ * @edev:              the extcon device that has the cable.
+ * @id:                        the unique id of each external connector
+ *                     in extcon enumeration.
+ * @prop:              the property id among enum extcon_property.
+ * @prop_val:          the pointer including the new value of property.
+ *
+ * The each property should be included in the list of supported properties
+ * according to the type of external connectors.
+ *
+ * Returns 0 if success or error number if fail
+ */
+int extcon_set_property(struct extcon_dev *edev, unsigned int id,
+                               unsigned int prop,
+                               union extcon_property_value prop_val)
+{
+       struct extcon_cable *cable;
+       unsigned long flags;
+       int index, ret = 0;
+
+       if (!edev)
+               return -EINVAL;
+
+       /* Check whether the property is supported or not */
+       if (!is_extcon_property_supported(id, prop))
+               return -EINVAL;
+
+       /* Find the cable index of external connector by using id */
+       index = find_cable_index_by_id(edev, id);
+       if (index < 0)
+               return index;
+
+       spin_lock_irqsave(&edev->lock, flags);
+
+       /* Check whether the property is available or not. */
+       if (!is_extcon_property_capability(edev, id, index, prop)) {
+               spin_unlock_irqrestore(&edev->lock, flags);
+               return -EPERM;
+       }
+
+       cable = &edev->cables[index];
+
+       /* Set the property value according to extcon type */
+       switch (prop) {
+       case EXTCON_PROP_USB_MIN ... EXTCON_PROP_USB_MAX:
+               cable->usb_propval[prop - EXTCON_PROP_USB_MIN] = prop_val;
+               break;
+       case EXTCON_PROP_CHG_MIN ... EXTCON_PROP_CHG_MAX:
+               cable->chg_propval[prop - EXTCON_PROP_CHG_MIN] = prop_val;
+               break;
+       case EXTCON_PROP_JACK_MIN ... EXTCON_PROP_JACK_MAX:
+               cable->jack_propval[prop - EXTCON_PROP_JACK_MIN] = prop_val;
+               break;
+       case EXTCON_PROP_DISP_MIN ... EXTCON_PROP_DISP_MAX:
+               cable->disp_propval[prop - EXTCON_PROP_DISP_MIN] = prop_val;
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+
+       spin_unlock_irqrestore(&edev->lock, flags);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(extcon_set_property);
+
+/**
+ * extcon_set_property_sync() - Set the property value of a specific cable
+                       with a notification.
+ * @prop_val:          the pointer including the new value of property.
+ *
+ * When setting the property value of external connector, the external connector
+ * should be attached. The each property should be included in the list of
+ * supported properties according to the type of external connectors.
+ *
+ * Returns 0 if success or error number if fail
+ */
+int extcon_set_property_sync(struct extcon_dev *edev, unsigned int id,
+                               unsigned int prop,
+                               union extcon_property_value prop_val)
+{
+       int ret;
+
+       ret = extcon_set_property(edev, id, prop, prop_val);
+       if (ret < 0)
+               return ret;
+
+       return extcon_sync(edev, id);
+}
+EXPORT_SYMBOL_GPL(extcon_set_property_sync);
+
+/**
+ * extcon_get_property_capability() - Get the capability of property
+ *                     of an external connector.
+ * @edev:              the extcon device that has the cable.
+ * @id:                        the unique id of each external connector
+ *                     in extcon enumeration.
+ * @prop:              the property id among enum extcon_property.
+ *
+ * Returns 1 if the property is available or 0 if not available.
+ */
+int extcon_get_property_capability(struct extcon_dev *edev, unsigned int id,
+                                       unsigned int prop)
+{
        int index;
 
        if (!edev)
                return -EINVAL;
 
+       /* Check whether the property is supported or not */
+       if (!is_extcon_property_supported(id, prop))
+               return -EINVAL;
+
+       /* Find the cable index of external connector by using id */
        index = find_cable_index_by_id(edev, id);
        if (index < 0)
                return index;
 
-       if (edev->max_supported && edev->max_supported <= index)
+       return is_extcon_property_capability(edev, id, index, prop);
+}
+EXPORT_SYMBOL_GPL(extcon_get_property_capability);
+
+/**
+ * extcon_set_property_capability() - Set the capability of a property
+ *                     of an external connector.
+ * @edev:              the extcon device that has the cable.
+ * @id:                        the unique id of each external connector
+ *                     in extcon enumeration.
+ * @prop:              the property id among enum extcon_property.
+ *
+ * This function set the capability of a property for an external connector
+ * to mark the bit in capability bitmap which mean the available state of
+ * a property.
+ *
+ * Returns 0 if success or error number if fail
+ */
+int extcon_set_property_capability(struct extcon_dev *edev, unsigned int id,
+                                       unsigned int prop)
+{
+       struct extcon_cable *cable;
+       int index, type, ret = 0;
+
+       if (!edev)
                return -EINVAL;
 
-       state = cable_state ? (1 << index) : 0;
-       return extcon_update_state(edev, 1 << index, state);
+       /* Check whether the property is supported or not. */
+       if (!is_extcon_property_supported(id, prop))
+               return -EINVAL;
+
+       /* Find the cable index of external connector by using id. */
+       index = find_cable_index_by_id(edev, id);
+       if (index < 0)
+               return index;
+
+       type = get_extcon_type(prop);
+       if (type < 0)
+               return type;
+
+       cable = &edev->cables[index];
+
+       switch (type) {
+       case EXTCON_TYPE_USB:
+               __set_bit(prop - EXTCON_PROP_USB_MIN, cable->usb_bits);
+               break;
+       case EXTCON_TYPE_CHG:
+               __set_bit(prop - EXTCON_PROP_CHG_MIN, cable->chg_bits);
+               break;
+       case EXTCON_TYPE_JACK:
+               __set_bit(prop - EXTCON_PROP_JACK_MIN, cable->jack_bits);
+               break;
+       case EXTCON_TYPE_DISP:
+               __set_bit(prop - EXTCON_PROP_DISP_MIN, cable->disp_bits);
+               break;
+       default:
+               ret = -EINVAL;
+       }
+
+       return ret;
 }
-EXPORT_SYMBOL_GPL(extcon_set_cable_state_);
+EXPORT_SYMBOL_GPL(extcon_set_property_capability);
 
 /**
  * extcon_get_extcon_dev() - Get the extcon device instance from the name