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

Commit 7524be37 authored by Mark Brown's avatar Mark Brown
Browse files

Merge remote-tracking branch 'asoc/topic/tas5086' into asoc-next

parents abdd182e 285d00c1
Loading
Loading
Loading
Loading
+109 −62
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@
#include <linux/i2c.h>
#include <linux/regmap.h>
#include <linux/spi/spi.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <sound/pcm.h>
@@ -244,6 +245,8 @@ struct tas5086_private {
	unsigned int	mclk, sclk;
	unsigned int	format;
	bool		deemph;
	unsigned int	charge_period;
	unsigned int	pwm_start_mid_z;
	/* Current sample rate for de-emphasis control */
	int		rate;
	/* GPIO driving Reset pin, if any */
@@ -456,6 +459,75 @@ static int tas5086_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
	return regmap_write(priv->regmap, TAS5086_SOFT_MUTE, val);
}

static void tas5086_reset(struct tas5086_private *priv)
{
	if (gpio_is_valid(priv->gpio_nreset)) {
		/* Reset codec - minimum assertion time is 400ns */
		gpio_direction_output(priv->gpio_nreset, 0);
		udelay(1);
		gpio_set_value(priv->gpio_nreset, 1);

		/* Codec needs ~15ms to wake up */
		msleep(15);
	}
}

/* charge period values in microseconds */
static const int tas5086_charge_period[] = {
	  13000,  16900,   23400,   31200,   41600,   54600,   72800,   96200,
	 130000, 156000,  234000,  312000,  416000,  546000,  728000,  962000,
	1300000, 169000, 2340000, 3120000, 4160000, 5460000, 7280000, 9620000,
};

static int tas5086_init(struct device *dev, struct tas5086_private *priv)
{
	int ret, i;

	/*
	 * If any of the channels is configured to start in Mid-Z mode,
	 * configure 'part 1' of the PWM starts to use Mid-Z, and tell
	 * all configured mid-z channels to start start under 'part 1'.
	 */
	if (priv->pwm_start_mid_z)
		regmap_write(priv->regmap, TAS5086_PWM_START,
			     TAS5086_PWM_START_MIDZ_FOR_START_1 |
				priv->pwm_start_mid_z);

	/* lookup and set split-capacitor charge period */
	if (priv->charge_period == 0) {
		regmap_write(priv->regmap, TAS5086_SPLIT_CAP_CHARGE, 0);
	} else {
		i = index_in_array(tas5086_charge_period,
				   ARRAY_SIZE(tas5086_charge_period),
				   priv->charge_period);
		if (i >= 0)
			regmap_write(priv->regmap, TAS5086_SPLIT_CAP_CHARGE,
				     i + 0x08);
		else
			dev_warn(dev,
				 "Invalid split-cap charge period of %d ns.\n",
				 priv->charge_period);
	}

	/* enable factory trim */
	ret = regmap_write(priv->regmap, TAS5086_OSC_TRIM, 0x00);
	if (ret < 0)
		return ret;

	/* start all channels */
	ret = regmap_write(priv->regmap, TAS5086_SYS_CONTROL_2, 0x20);
	if (ret < 0)
		return ret;

	/* mute all channels for now */
	ret = regmap_write(priv->regmap, TAS5086_SOFT_MUTE,
			   TAS5086_SOFT_MUTE_ALL);
	if (ret < 0)
		return ret;

	return 0;
}

/* TAS5086 controls */
static const DECLARE_TLV_DB_SCALE(tas5086_dac_tlv, -10350, 50, 1);

@@ -691,14 +763,39 @@ static struct snd_soc_dai_driver tas5086_dai = {
};

#ifdef CONFIG_PM
static int tas5086_soc_suspend(struct snd_soc_codec *codec)
{
	struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
	int ret;

	/* Shut down all channels */
	ret = regmap_write(priv->regmap, TAS5086_SYS_CONTROL_2, 0x60);
	if (ret < 0)
		return ret;

	return 0;
}

static int tas5086_soc_resume(struct snd_soc_codec *codec)
{
	struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
	int ret;

	tas5086_reset(priv);
	regcache_mark_dirty(priv->regmap);

	ret = tas5086_init(codec->dev, priv);
	if (ret < 0)
		return ret;

	ret = regcache_sync(priv->regmap);
	if (ret < 0)
		return ret;

	/* Restore codec state */
	return regcache_sync(priv->regmap);
	return 0;
}
#else
#define tas5086_soc_suspend	NULL
#define tas5086_soc_resume	NULL
#endif /* CONFIG_PM */

@@ -710,23 +807,19 @@ static const struct of_device_id tas5086_dt_ids[] = {
MODULE_DEVICE_TABLE(of, tas5086_dt_ids);
#endif

/* charge period values in microseconds */
static const int tas5086_charge_period[] = {
	  13000,  16900,   23400,   31200,   41600,   54600,   72800,   96200,
	 130000, 156000,  234000,  312000,  416000,  546000,  728000,  962000,
	1300000, 169000, 2340000, 3120000, 4160000, 5460000, 7280000, 9620000,
};

static int tas5086_probe(struct snd_soc_codec *codec)
{
	struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
	int charge_period = 1300000; /* hardware default is 1300 ms */
	u8 pwm_start_mid_z = 0;
	int i, ret;

	priv->pwm_start_mid_z = 0;
	priv->charge_period = 1300000; /* hardware default is 1300 ms */

	if (of_match_device(of_match_ptr(tas5086_dt_ids), codec->dev)) {
		struct device_node *of_node = codec->dev->of_node;
		of_property_read_u32(of_node, "ti,charge-period", &charge_period);

		of_property_read_u32(of_node, "ti,charge-period",
				     &priv->charge_period);

		for (i = 0; i < 6; i++) {
			char name[25];
@@ -735,43 +828,11 @@ static int tas5086_probe(struct snd_soc_codec *codec)
				 "ti,mid-z-channel-%d", i + 1);

			if (of_get_property(of_node, name, NULL) != NULL)
				pwm_start_mid_z |= 1 << i;
				priv->pwm_start_mid_z |= 1 << i;
		}
	}

	/*
	 * If any of the channels is configured to start in Mid-Z mode,
	 * configure 'part 1' of the PWM starts to use Mid-Z, and tell
	 * all configured mid-z channels to start start under 'part 1'.
	 */
	if (pwm_start_mid_z)
		regmap_write(priv->regmap, TAS5086_PWM_START,
			     TAS5086_PWM_START_MIDZ_FOR_START_1 |
				pwm_start_mid_z);

	/* lookup and set split-capacitor charge period */
	if (charge_period == 0) {
		regmap_write(priv->regmap, TAS5086_SPLIT_CAP_CHARGE, 0);
	} else {
		i = index_in_array(tas5086_charge_period,
				   ARRAY_SIZE(tas5086_charge_period),
				   charge_period);
		if (i >= 0)
			regmap_write(priv->regmap, TAS5086_SPLIT_CAP_CHARGE,
				     i + 0x08);
		else
			dev_warn(codec->dev,
				 "Invalid split-cap charge period of %d ns.\n",
				 charge_period);
	}

	/* enable factory trim */
	ret = regmap_write(priv->regmap, TAS5086_OSC_TRIM, 0x00);
	if (ret < 0)
		return ret;

	/* start all channels */
	ret = regmap_write(priv->regmap, TAS5086_SYS_CONTROL_2, 0x20);
	ret = tas5086_init(codec->dev, priv);
	if (ret < 0)
		return ret;

@@ -780,12 +841,6 @@ static int tas5086_probe(struct snd_soc_codec *codec)
	if (ret < 0)
		return ret;

	/* mute all channels for now */
	ret = regmap_write(priv->regmap, TAS5086_SOFT_MUTE,
			   TAS5086_SOFT_MUTE_ALL);
	if (ret < 0)
		return ret;

	return 0;
}

@@ -803,6 +858,7 @@ static int tas5086_remove(struct snd_soc_codec *codec)
static struct snd_soc_codec_driver soc_codec_dev_tas5086 = {
	.probe			= tas5086_probe,
	.remove			= tas5086_remove,
	.suspend		= tas5086_soc_suspend,
	.resume			= tas5086_soc_resume,
	.controls		= tas5086_controls,
	.num_controls		= ARRAY_SIZE(tas5086_controls),
@@ -862,17 +918,8 @@ static int tas5086_i2c_probe(struct i2c_client *i2c,
		if (devm_gpio_request(dev, gpio_nreset, "TAS5086 Reset"))
			gpio_nreset = -EINVAL;

	if (gpio_is_valid(gpio_nreset)) {
		/* Reset codec - minimum assertion time is 400ns */
		gpio_direction_output(gpio_nreset, 0);
		udelay(1);
		gpio_set_value(gpio_nreset, 1);

		/* Codec needs ~15ms to wake up */
		msleep(15);
	}

	priv->gpio_nreset = gpio_nreset;
	tas5086_reset(priv);

	/* The TAS5086 always returns 0x03 in its TAS5086_DEV_ID register */
	ret = regmap_read(priv->regmap, TAS5086_DEV_ID, &i);