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

Commit 41e071e6 authored by Karthikeyan Mani's avatar Karthikeyan Mani Committed by Meng Wang
Browse files

drivers: soc: qcom: notify drivers registering first time



Send usbc mode at register function so that all drivers
registering first time will get the notification of
current usb connection type, if any.

Change-Id: Ifac7af1ff546a17bc6f382246ae0aeec5194ca9f
Signed-off-by: default avatarKarthikeyan Mani <kmani@codeaurora.org>
parent 55ea5fc9
Loading
Loading
Loading
Loading
+52 −32
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
 */

#include <linux/kernel.h>
@@ -7,6 +7,7 @@
#include <linux/power_supply.h>
#include <linux/regmap.h>
#include <linux/i2c.h>
#include <linux/mutex.h>
#include <linux/soc/qcom/fsa4480-i2c.h>

#define FSA4480_I2C_NAME	"fsa4480-driver"
@@ -33,6 +34,7 @@ struct fsa4480_priv {
	atomic_t usbc_mode;
	struct work_struct usbc_analog_work;
	struct blocking_notifier_head fsa4480_notifier;
	struct mutex notification_lock;
};

struct fsa4480_reg_val {
@@ -124,6 +126,51 @@ static int fsa4480_usbc_event_changed(struct notifier_block *nb,
	return ret;
}

static int fsa4480_usbc_analog_setup_switches(struct fsa4480_priv *fsa_priv)
{
	int rc = 0;
	union power_supply_propval mode;
	struct device *dev;

	if (!fsa_priv)
		return -EINVAL;
	dev = fsa_priv->dev;
	if (!dev)
		return -EINVAL;

	mutex_lock(&fsa_priv->notification_lock);
	/* get latest mode again within locked context */
	rc = power_supply_get_property(fsa_priv->usb_psy,
			POWER_SUPPLY_PROP_TYPEC_MODE, &mode);
	if (rc) {
		dev_err(dev, "%s: Unable to read USB TYPEC_MODE: %d\n",
			__func__, rc);
		goto done;
	}
	dev_dbg(dev, "%s: setting GPIOs active = %d\n",
		__func__, mode.intval != POWER_SUPPLY_TYPEC_NONE);

	if (mode.intval != POWER_SUPPLY_TYPEC_NONE) {
		/* activate switches */
		fsa4480_usbc_update_settings(fsa_priv, 0x00, 0x9F);

		/* notify call chain on event */
		blocking_notifier_call_chain(&fsa_priv->fsa4480_notifier,
		POWER_SUPPLY_TYPEC_SINK_AUDIO_ADAPTER, NULL);
	} else {
		/* notify call chain on event */
		blocking_notifier_call_chain(&fsa_priv->fsa4480_notifier,
				POWER_SUPPLY_TYPEC_NONE, NULL);

		/* deactivate switches */
		fsa4480_usbc_update_settings(fsa_priv, 0x18, 0x98);
	}

done:
	mutex_unlock(&fsa_priv->notification_lock);
	return rc;
}

/*
 * fsa4480_reg_notifier - register notifier block with fsa driver
 *
@@ -157,9 +204,7 @@ int fsa4480_reg_notifier(struct notifier_block *nb,
	 */
	dev_dbg(fsa_priv->dev, "%s: verify if USB adapter is already inserted\n",
		__func__);
	rc = fsa4480_usbc_event_changed(&fsa_priv->psy_nb,
					     PSY_EVENT_PROP_CHANGED,
					     fsa_priv->usb_psy);
	rc = fsa4480_usbc_analog_setup_switches(fsa_priv);

	return rc;
}
@@ -186,7 +231,6 @@ int fsa4480_unreg_notifier(struct notifier_block *nb,
	if (!fsa_priv)
		return -EINVAL;

	atomic_set(&(fsa_priv->usbc_mode), 0);
	fsa4480_usbc_update_settings(fsa_priv, 0x18, 0x98);
	return blocking_notifier_chain_unregister
					(&fsa_priv->fsa4480_notifier, nb);
@@ -258,31 +302,6 @@ int fsa4480_switch_event(struct device_node *node,
}
EXPORT_SYMBOL(fsa4480_switch_event);

static int fsa4480_usbc_analog_setup_switches
			(struct fsa4480_priv *fsa_priv, bool active)
{
	dev_dbg(fsa_priv->dev, "%s: setting GPIOs active = %d\n",
		__func__, active);

	if (active) {
		/* activate switches */
		fsa4480_usbc_update_settings(fsa_priv, 0x00, 0x9F);

		/* notify call chain on event */
		blocking_notifier_call_chain(&fsa_priv->fsa4480_notifier,
		POWER_SUPPLY_TYPEC_SINK_AUDIO_ADAPTER, NULL);
	} else {
		/* notify call chain on event */
		blocking_notifier_call_chain(&fsa_priv->fsa4480_notifier,
				POWER_SUPPLY_TYPEC_NONE, NULL);

		/* deactivate switches */
		fsa4480_usbc_update_settings(fsa_priv, 0x18, 0x98);
	}

	return 0;
}

static void fsa4480_usbc_analog_work_fn(struct work_struct *work)
{
	struct fsa4480_priv *fsa_priv =
@@ -292,8 +311,7 @@ static void fsa4480_usbc_analog_work_fn(struct work_struct *work)
		pr_err("%s: fsa container invalid\n", __func__);
		return;
	}
	fsa4480_usbc_analog_setup_switches(fsa_priv,
		atomic_read(&(fsa_priv->usbc_mode)) != POWER_SUPPLY_TYPEC_NONE);
	fsa4480_usbc_analog_setup_switches(fsa_priv);
	pm_relax(fsa_priv->dev);
}

@@ -351,6 +369,7 @@ static int fsa4480_probe(struct i2c_client *i2c,
		goto err_supply;
	}

	mutex_init(&fsa_priv->notification_lock);
	i2c_set_clientdata(i2c, fsa_priv);

	INIT_WORK(&fsa_priv->usbc_analog_work,
@@ -384,6 +403,7 @@ static int fsa4480_remove(struct i2c_client *i2c)
	/* deregister from PMI */
	power_supply_unreg_notifier(&fsa_priv->psy_nb);
	power_supply_put(fsa_priv->usb_psy);
	mutex_destroy(&fsa_priv->notification_lock);
	dev_set_drvdata(&i2c->dev, NULL);

	return 0;