Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 073a457d authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman
Browse files

Merge tag 'extcon-next-for-4.12' of...

Merge tag 'extcon-next-for-4.12' of git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/extcon into char-misc-next

Update extcon for 4.12

Detailed description for this pull request:
1. Add new 'extcon-intel-cht-wc.c' driver
- Intel Cherrytrail Whiskey Cove PMIC extcon driver supports
the detection of the charger connectors and the control.

2. Add new extcon API to monitor the all external connectors.
- The extcon consumer might need to monitor the all supported external
connectors from the extcon device. Before, the extcon consumer
should have each notifier_block structure for each external connector.

In order to support the requirement, the extcon adds new
extcon_register_notifier_all() API. The extcon consumer is able
to monitor the state change of all supported external connectors
from the extcon device by using only one notifier_block.

- extcon_(register|unregister)_notifier_all(struct extcon_dev *edev
				struct notifier_block *nb)
- devm_extcon_(register|unregister)_notifier_all(struct device *dev,
				struct extcon_dev *edev
				struct notifier_block *nb)

3. Remove porting compatibility of old switch class
- The extcon removes the porting compatibility of old switch class
because there are no any use-case and requirement of switch class.

4. Update the extcon drivers and Fix the minor issues
- Revert the ACPI gpio interface on the extcon-usb-gpioc.c.
- Fix the issues related to the suspend-to-ram for both extcon-usb-gpio.c
  and extcon-palmas.c.
- Add warning message for extcon-arizona.c when headphone detection is not
  finished.
parents 615cdd7c 70641a0a
Loading
Loading
Loading
Loading
+0 −123
Original line number Diff line number Diff line

	Staging/Android Switch Class Porting Guide
	(linux/drivers/staging/android/switch)
	(c) Copyright 2012 Samsung Electronics

AUTHORS
MyungJoo Ham <myungjoo.ham@samsung.com>

/*****************************************************************
 * CHAPTER 1.                                                    *
 * PORTING SWITCH CLASS DEVICE DRIVERS                           *
 *****************************************************************/

****** STEP 1. Basic Functionality
	No extcon extended feature, but switch features only.

- struct switch_dev (fed to switch_dev_register/unregister)
    @name: no change
    @dev: no change
    @index: drop (not used in switch device driver side anyway)
    @state: no change
	If you have used @state with magic numbers, keep it
	at this step.
    @print_name: no change but type change (switch_dev->extcon_dev)
    @print_state: no change but type change (switch_dev->extcon_dev)

- switch_dev_register(sdev, dev)
	=> extcon_dev_register(edev)
	: type change (sdev->edev)
	: remove second param('dev'). if edev has parent device, should store
	  'dev' to 'edev.dev.parent' before registering extcon device
- switch_dev_unregister(sdev)
	=> extcon_dev_unregister(edev)
	: no change but type change (sdev->edev)
- switch_get_state(sdev)
	=> extcon_get_state(edev)
	: no change but type change (sdev->edev) and (return: int->u32)
- switch_set_state(sdev, state)
	=> extcon_set_state(edev, state)
	: no change but type change (sdev->edev) and (state: int->u32)

With this changes, the ex-switch extcon class device works as it once
worked as switch class device. However, it will now have additional
interfaces (both ABI and in-kernel API) and different ABI locations.
However, if CONFIG_ANDROID is enabled without CONFIG_ANDROID_SWITCH,
/sys/class/switch/* will be symbolically linked to /sys/class/extcon/
so that they are still compatible with legacy userspace processes.

****** STEP 2. Multistate (no more magic numbers in state value)
	Extcon's extended features for switch device drivers with
	complex features usually required magic numbers in state
	value of switch_dev. With extcon, such magic numbers that
	support multiple cables are no more required or supported.

  1. Define cable names at edev->supported_cable.
  2. (Recommended) remove print_state callback.
  3. Use extcon_get_cable_state_(edev, index) or
   extcon_get_cable_state(edev, cable_name) instead of
   extcon_get_state(edev) if you intend to get a state of a specific
   cable. Same for set_state. This way, you can remove the usage of
   magic numbers in state value.
  4. Use extcon_update_state() if you are updating specific bits of
   the state value.

Example: a switch device driver w/ magic numbers for two cables.
	"0x00": no cables connected.
	"0x01": cable 1 connected
	"0x02": cable 2 connected
	"0x03": cable 1 and 2 connected
  1. edev->supported_cable = {"1", "2", NULL};
  2. edev->print_state = NULL;
  3. extcon_get_cable_state_(edev, 0) shows cable 1's state.
     extcon_get_cable_state(edev, "1") shows cable 1's state.
     extcon_set_cable_state_(edev, 1) sets cable 2's state.
     extcon_set_cable_state(edev, "2") sets cable 2's state
  4. extcon_update_state(edev, 0x01, 0) sets the least bit's 0.

****** STEP 3. Notify other device drivers

  You can notify others of the cable attach/detach events with
notifier chains.

  At the side of other device drivers (the extcon device itself
does not need to get notified of its own events), there are two
methods to register notifier_block for cable events:
(a) for a specific cable or (b) for every cable.

  (a) extcon_register_interest(obj, extcon_name, cable_name, nb)
	Example: want to get news of "MAX8997_MUIC"'s "USB" cable

	obj = kzalloc(sizeof(struct extcon_specific_cable_nb),
		      GFP_KERNEL);
	nb->notifier_call = the_callback_to_handle_usb;

	extcon_register_intereset(obj, "MAX8997_MUIC", "USB", nb);

  (b) extcon_register_notifier(edev, nb)
	Call nb for any changes in edev.

  Please note that in order to properly behave with method (a),
the extcon device driver should support multistate feature (STEP 2).

****** STEP 4. Inter-cable relation (mutually exclusive)

  You can provide inter-cable mutually exclusiveness information
for an extcon device. When cables A and B are declared to be mutually
exclusive, the two cables cannot be in ATTACHED state simulteneously.


/*****************************************************************
 * CHAPTER 2.                                                    *
 * PORTING USERSPACE w/ SWITCH CLASS DEVICE SUPPORT              *
 *****************************************************************/

****** ABI Location

  If "CONFIG_ANDROID" is enabled, /sys/class/switch/* are created
as symbolic links to /sys/class/extcon/*.

  The two files of switch class, name and state, are provided with
extcon, too. When the multistate support (STEP 2 of CHAPTER 1.) is
not enabled or print_state callback is supplied, the output of
state ABI is same with switch class.
+7 −0
Original line number Diff line number Diff line
@@ -52,6 +52,13 @@ config EXTCON_INTEL_INT3496
	  This ACPI device is typically found on Intel Baytrail or Cherrytrail
	  based tablets, or other Baytrail / Cherrytrail devices.

config EXTCON_INTEL_CHT_WC
	tristate "Intel Cherrytrail Whiskey Cove PMIC extcon driver"
	depends on INTEL_SOC_PMIC_CHTWC
	help
	  Say Y here to enable extcon support for charger detection / control
	  on the Intel Cherrytrail Whiskey Cove PMIC.

config EXTCON_MAX14577
	tristate "Maxim MAX14577/77836 EXTCON Support"
	depends on MFD_MAX14577
+1 −0
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@ obj-$(CONFIG_EXTCON_ARIZONA) += extcon-arizona.o
obj-$(CONFIG_EXTCON_AXP288)	+= extcon-axp288.o
obj-$(CONFIG_EXTCON_GPIO)	+= extcon-gpio.o
obj-$(CONFIG_EXTCON_INTEL_INT3496) += extcon-intel-int3496.o
obj-$(CONFIG_EXTCON_INTEL_CHT_WC) += extcon-intel-cht-wc.o
obj-$(CONFIG_EXTCON_MAX14577)	+= extcon-max14577.o
obj-$(CONFIG_EXTCON_MAX3355)	+= extcon-max3355.o
obj-$(CONFIG_EXTCON_MAX77693)	+= extcon-max77693.o
+61 −0
Original line number Diff line number Diff line
@@ -50,6 +50,13 @@ static void devm_extcon_dev_notifier_unreg(struct device *dev, void *res)
	extcon_unregister_notifier(this->edev, this->id, this->nb);
}

static void devm_extcon_dev_notifier_all_unreg(struct device *dev, void *res)
{
	struct extcon_dev_notifier_devres *this = res;

	extcon_unregister_notifier_all(this->edev, this->nb);
}

/**
 * devm_extcon_dev_allocate - Allocate managed extcon device
 * @dev:		device owning the extcon device being created
@@ -214,3 +221,57 @@ void devm_extcon_unregister_notifier(struct device *dev,
			       devm_extcon_dev_match, edev));
}
EXPORT_SYMBOL(devm_extcon_unregister_notifier);

/**
 * devm_extcon_register_notifier_all()
 *		- Resource-managed extcon_register_notifier_all()
 * @dev:	device to allocate extcon device
 * @edev:	the extcon device that has the external connecotr.
 * @nb:		a notifier block to be registered.
 *
 * This function manages automatically the notifier of extcon device using
 * device resource management and simplify the control of unregistering
 * the notifier of extcon device. To get more information, refer that function.
 *
 * Returns 0 if success or negaive error number if failure.
 */
int devm_extcon_register_notifier_all(struct device *dev, struct extcon_dev *edev,
				struct notifier_block *nb)
{
	struct extcon_dev_notifier_devres *ptr;
	int ret;

	ptr = devres_alloc(devm_extcon_dev_notifier_all_unreg, sizeof(*ptr),
				GFP_KERNEL);
	if (!ptr)
		return -ENOMEM;

	ret = extcon_register_notifier_all(edev, nb);
	if (ret) {
		devres_free(ptr);
		return ret;
	}

	ptr->edev = edev;
	ptr->nb = nb;
	devres_add(dev, ptr);

	return 0;
}
EXPORT_SYMBOL(devm_extcon_register_notifier_all);

/**
 * devm_extcon_unregister_notifier_all()
 *		- Resource-managed extcon_unregister_notifier_all()
 * @dev:	device to allocate extcon device
 * @edev:	the extcon device that has the external connecotr.
 * @nb:		a notifier block to be registered.
 */
void devm_extcon_unregister_notifier_all(struct device *dev,
				struct extcon_dev *edev,
				struct notifier_block *nb)
{
	WARN_ON(devres_release(dev, devm_extcon_dev_notifier_all_unreg,
			       devm_extcon_dev_match, edev));
}
EXPORT_SYMBOL(devm_extcon_unregister_notifier_all);
+46 −0
Original line number Diff line number Diff line
@@ -51,6 +51,9 @@
#define HPDET_DEBOUNCE 500
#define DEFAULT_MICD_TIMEOUT 2000

#define ARIZONA_HPDET_WAIT_COUNT 15
#define ARIZONA_HPDET_WAIT_DELAY_MS 20

#define QUICK_HEADPHONE_MAX_OHM 3
#define MICROPHONE_MIN_OHM      1257
#define MICROPHONE_MAX_OHM      30000
@@ -1049,6 +1052,40 @@ static void arizona_hpdet_work(struct work_struct *work)
	mutex_unlock(&info->lock);
}

static int arizona_hpdet_wait(struct arizona_extcon_info *info)
{
	struct arizona *arizona = info->arizona;
	unsigned int val;
	int i, ret;

	for (i = 0; i < ARIZONA_HPDET_WAIT_COUNT; i++) {
		ret = regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_2,
				&val);
		if (ret) {
			dev_err(arizona->dev,
				"Failed to read HPDET state: %d\n", ret);
			return ret;
		}

		switch (info->hpdet_ip_version) {
		case 0:
			if (val & ARIZONA_HP_DONE)
				return 0;
			break;
		default:
			if (val & ARIZONA_HP_DONE_B)
				return 0;
			break;
		}

		msleep(ARIZONA_HPDET_WAIT_DELAY_MS);
	}

	dev_warn(arizona->dev, "HPDET did not appear to complete\n");

	return -ETIMEDOUT;
}

static irqreturn_t arizona_jackdet(int irq, void *data)
{
	struct arizona_extcon_info *info = data;
@@ -1155,6 +1192,15 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
					"Removal report failed: %d\n", ret);
		}

		/*
		 * If the jack was removed during a headphone detection we
		 * need to wait for the headphone detection to finish, as
		 * it can not be aborted. We don't want to be able to start
		 * a new headphone detection from a fresh insert until this
		 * one is finished.
		 */
		arizona_hpdet_wait(info);

		regmap_update_bits(arizona->regmap,
				   ARIZONA_JACK_DETECT_DEBOUNCE,
				   ARIZONA_MICD_CLAMP_DB | ARIZONA_JD1_DB,
Loading