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

Commit aaa36d3a authored by Mark Brown's avatar Mark Brown
Browse files

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

parents 4c1c16d9 bd023ada
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
Texas Instruments TAS5711/TAS5717/TAS5719 stereo power amplifiers
Texas Instruments TAS5711/TAS5717/TAS5719/TAS5721 stereo power amplifiers

The codec is controlled through an I2C interface.  It also has two other
signals that can be wired up to GPIOs: reset (strongly recommended), and
@@ -6,7 +6,11 @@ powerdown (optional).

Required properties:

- compatible: "ti,tas5711", "ti,tas5717", or "ti,tas5719"
- compatible: should be one of the following:
  - "ti,tas5711",
  - "ti,tas5717",
  - "ti,tas5719",
  - "ti,tas5721"
- reg: The I2C address of the device
- #sound-dai-cells: must be equal to 0

@@ -25,6 +29,8 @@ Optional properties:
- PVDD_B-supply: regulator phandle for the PVDD_B supply (5711)
- PVDD_C-supply: regulator phandle for the PVDD_C supply (5711)
- PVDD_D-supply: regulator phandle for the PVDD_D supply (5711)
- DRVDD-supply: regulator phandle for the DRVDD supply (5721)
- PVDD-supply: regulator phandle for the PVDD supply (5721)

Example:

+25 −0
Original line number Diff line number Diff line
Texas Instruments TAS5720 Mono Audio amplifier

The TAS5720 serial control bus communicates through the I2C protocol only. The
serial bus is also used for periodic codec fault checking/reporting during
audio playback. For more product information please see the links below:

http://www.ti.com/product/TAS5720L
http://www.ti.com/product/TAS5720M

Required properties:

- compatible : "ti,tas5720"
- reg : I2C slave address
- dvdd-supply : phandle to a 3.3-V supply for the digital circuitry
- pvdd-supply : phandle to a supply used for the Class-D amp and the analog

Example:

tas5720: tas5720@6c {
	status = "okay";
	compatible = "ti,tas5720";
	reg = <0x6c>;
	dvdd-supply = <&vdd_3v3_reg>;
	pvdd-supply = <&amp_supply_reg>;
};
+9 −1
Original line number Diff line number Diff line
@@ -127,6 +127,7 @@ config SND_SOC_ALL_CODECS
	select SND_SOC_TAS2552 if I2C
	select SND_SOC_TAS5086 if I2C
	select SND_SOC_TAS571X if I2C
	select SND_SOC_TAS5720 if I2C
	select SND_SOC_TFA9879 if I2C
	select SND_SOC_TLV320AIC23_I2C if I2C
	select SND_SOC_TLV320AIC23_SPI if SPI_MASTER
@@ -753,9 +754,16 @@ config SND_SOC_TAS5086
	depends on I2C

config SND_SOC_TAS571X
	tristate "Texas Instruments TAS5711/TAS5717/TAS5719 power amplifiers"
	tristate "Texas Instruments TAS5711/TAS5717/TAS5719/TAS5721 power amplifiers"
	depends on I2C

config SND_SOC_TAS5720
	tristate "Texas Instruments TAS5720 Mono Audio amplifier"
	depends on I2C
	help
	  Enable support for Texas Instruments TAS5720L/M high-efficiency mono
	  Class-D audio power amplifiers.

config SND_SOC_TFA9879
	tristate "NXP Semiconductors TFA9879 amplifier"
	depends on I2C
+2 −0
Original line number Diff line number Diff line
@@ -132,6 +132,7 @@ snd-soc-stac9766-objs := stac9766.o
snd-soc-sti-sas-objs := sti-sas.o
snd-soc-tas5086-objs := tas5086.o
snd-soc-tas571x-objs := tas571x.o
snd-soc-tas5720-objs := tas5720.o
snd-soc-tfa9879-objs := tfa9879.o
snd-soc-tlv320aic23-objs := tlv320aic23.o
snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o
@@ -342,6 +343,7 @@ obj-$(CONFIG_SND_SOC_STI_SAS) += snd-soc-sti-sas.o
obj-$(CONFIG_SND_SOC_TAS2552)	+= snd-soc-tas2552.o
obj-$(CONFIG_SND_SOC_TAS5086)	+= snd-soc-tas5086.o
obj-$(CONFIG_SND_SOC_TAS571X)	+= snd-soc-tas571x.o
obj-$(CONFIG_SND_SOC_TAS5720)	+= snd-soc-tas5720.o
obj-$(CONFIG_SND_SOC_TFA9879)	+= snd-soc-tfa9879.o
obj-$(CONFIG_SND_SOC_TLV320AIC23)	+= snd-soc-tlv320aic23.o
obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C)	+= snd-soc-tlv320aic23-i2c.o
+129 −12
Original line number Diff line number Diff line
@@ -4,6 +4,9 @@
 * Copyright (C) 2015 Google, Inc.
 * Copyright (c) 2013 Daniel Mack <zonque@gmail.com>
 *
 * TAS5721 support:
 * Copyright (C) 2016 Petr Kulhavy, Barix AG <petr@barix.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
@@ -57,6 +60,10 @@ static int tas571x_register_size(struct tas571x_private *priv, unsigned int reg)
	case TAS571X_CH1_VOL_REG:
	case TAS571X_CH2_VOL_REG:
		return priv->chip->vol_reg_size;
	case TAS571X_INPUT_MUX_REG:
	case TAS571X_CH4_SRC_SELECT_REG:
	case TAS571X_PWM_MUX_REG:
		return 4;
	default:
		return 1;
	}
@@ -167,6 +174,23 @@ static int tas571x_hw_params(struct snd_pcm_substream *substream,
				  TAS571X_SDI_FMT_MASK, val);
}

static int tas571x_mute(struct snd_soc_dai *dai, int mute)
{
	struct snd_soc_codec *codec = dai->codec;
	u8 sysctl2;
	int ret;

	sysctl2 = mute ? TAS571X_SYS_CTRL_2_SDN_MASK : 0;

	ret = snd_soc_update_bits(codec,
			    TAS571X_SYS_CTRL_2_REG,
		     TAS571X_SYS_CTRL_2_SDN_MASK,
		     sysctl2);
	usleep_range(1000, 2000);

	return ret;
}

static int tas571x_set_bias_level(struct snd_soc_codec *codec,
				  enum snd_soc_bias_level level)
{
@@ -214,6 +238,7 @@ static int tas571x_set_bias_level(struct snd_soc_codec *codec,
static const struct snd_soc_dai_ops tas571x_dai_ops = {
	.set_fmt	= tas571x_set_dai_fmt,
	.hw_params	= tas571x_hw_params,
	.digital_mute	= tas571x_mute,
};

static const char *const tas5711_supply_names[] = {
@@ -241,6 +266,26 @@ static const struct snd_kcontrol_new tas5711_controls[] = {
		   1, 1),
};

static const struct regmap_range tas571x_readonly_regs_range[] = {
	regmap_reg_range(TAS571X_CLK_CTRL_REG,  TAS571X_DEV_ID_REG),
};

static const struct regmap_range tas571x_volatile_regs_range[] = {
	regmap_reg_range(TAS571X_CLK_CTRL_REG,  TAS571X_ERR_STATUS_REG),
	regmap_reg_range(TAS571X_OSC_TRIM_REG,  TAS571X_OSC_TRIM_REG),
};

static const struct regmap_access_table tas571x_write_regs = {
	.no_ranges =	tas571x_readonly_regs_range,
	.n_no_ranges =	ARRAY_SIZE(tas571x_readonly_regs_range),
};

static const struct regmap_access_table tas571x_volatile_regs = {
	.yes_ranges =	tas571x_volatile_regs_range,
	.n_yes_ranges =	ARRAY_SIZE(tas571x_volatile_regs_range),

};

static const struct reg_default tas5711_reg_defaults[] = {
	{ 0x04, 0x05 },
	{ 0x05, 0x40 },
@@ -260,6 +305,8 @@ static const struct regmap_config tas5711_regmap_config = {
	.reg_defaults			= tas5711_reg_defaults,
	.num_reg_defaults		= ARRAY_SIZE(tas5711_reg_defaults),
	.cache_type			= REGCACHE_RBTREE,
	.wr_table			= &tas571x_write_regs,
	.volatile_table			= &tas571x_volatile_regs,
};

static const struct tas571x_chip tas5711_chip = {
@@ -314,6 +361,8 @@ static const struct regmap_config tas5717_regmap_config = {
	.reg_defaults			= tas5717_reg_defaults,
	.num_reg_defaults		= ARRAY_SIZE(tas5717_reg_defaults),
	.cache_type			= REGCACHE_RBTREE,
	.wr_table			= &tas571x_write_regs,
	.volatile_table			= &tas571x_volatile_regs,
};

/* This entry is reused for tas5719 as the software interface is identical. */
@@ -326,6 +375,77 @@ static const struct tas571x_chip tas5717_chip = {
	.vol_reg_size			= 2,
};

static const char *const tas5721_supply_names[] = {
	"AVDD",
	"DVDD",
	"DRVDD",
	"PVDD",
};

static const struct snd_kcontrol_new tas5721_controls[] = {
	SOC_SINGLE_TLV("Master Volume",
		       TAS571X_MVOL_REG,
		       0, 0xff, 1, tas5711_volume_tlv),
	SOC_DOUBLE_R_TLV("Speaker Volume",
			 TAS571X_CH1_VOL_REG,
			 TAS571X_CH2_VOL_REG,
			 0, 0xff, 1, tas5711_volume_tlv),
	SOC_DOUBLE("Speaker Switch",
		   TAS571X_SOFT_MUTE_REG,
		   TAS571X_SOFT_MUTE_CH1_SHIFT, TAS571X_SOFT_MUTE_CH2_SHIFT,
		   1, 1),
};

static const struct reg_default tas5721_reg_defaults[] = {
	{TAS571X_CLK_CTRL_REG,		0x6c},
	{TAS571X_DEV_ID_REG,		0x00},
	{TAS571X_ERR_STATUS_REG,	0x00},
	{TAS571X_SYS_CTRL_1_REG,	0xa0},
	{TAS571X_SDI_REG,		0x05},
	{TAS571X_SYS_CTRL_2_REG,	0x40},
	{TAS571X_SOFT_MUTE_REG,		0x00},
	{TAS571X_MVOL_REG,		0xff},
	{TAS571X_CH1_VOL_REG,		0x30},
	{TAS571X_CH2_VOL_REG,		0x30},
	{TAS571X_CH3_VOL_REG,		0x30},
	{TAS571X_VOL_CFG_REG,		0x91},
	{TAS571X_MODULATION_LIMIT_REG,	0x02},
	{TAS571X_IC_DELAY_CH1_REG,	0xac},
	{TAS571X_IC_DELAY_CH2_REG,	0x54},
	{TAS571X_IC_DELAY_CH3_REG,	0xac},
	{TAS571X_IC_DELAY_CH4_REG,	0x54},
	{TAS571X_PWM_CH_SDN_GROUP_REG,	0x30},
	{TAS571X_START_STOP_PERIOD_REG,	0x0f},
	{TAS571X_OSC_TRIM_REG,		0x82},
	{TAS571X_BKND_ERR_REG,		0x02},
	{TAS571X_INPUT_MUX_REG,		0x17772},
	{TAS571X_CH4_SRC_SELECT_REG,	0x4303},
	{TAS571X_PWM_MUX_REG,		0x1021345},
};

static const struct regmap_config tas5721_regmap_config = {
	.reg_bits			= 8,
	.val_bits			= 32,
	.max_register			= 0xff,
	.reg_read			= tas571x_reg_read,
	.reg_write			= tas571x_reg_write,
	.reg_defaults			= tas5721_reg_defaults,
	.num_reg_defaults		= ARRAY_SIZE(tas5721_reg_defaults),
	.cache_type			= REGCACHE_RBTREE,
	.wr_table			= &tas571x_write_regs,
	.volatile_table			= &tas571x_volatile_regs,
};


static const struct tas571x_chip tas5721_chip = {
	.supply_names			= tas5721_supply_names,
	.num_supply_names		= ARRAY_SIZE(tas5721_supply_names),
	.controls			= tas5711_controls,
	.num_controls			= ARRAY_SIZE(tas5711_controls),
	.regmap_config			= &tas5721_regmap_config,
	.vol_reg_size			= 1,
};

static const struct snd_soc_dapm_widget tas571x_dapm_widgets[] = {
	SND_SOC_DAPM_DAC("DACL", NULL, SND_SOC_NOPM, 0, 0),
	SND_SOC_DAPM_DAC("DACR", NULL, SND_SOC_NOPM, 0, 0),
@@ -386,11 +506,10 @@ static int tas571x_i2c_probe(struct i2c_client *client,
	i2c_set_clientdata(client, priv);

	of_id = of_match_device(tas571x_of_match, dev);
	if (!of_id) {
		dev_err(dev, "Unknown device type\n");
		return -EINVAL;
	}
	if (of_id)
		priv->chip = of_id->data;
	else
		priv->chip = (void *) id->driver_data;

	priv->mclk = devm_clk_get(dev, "mclk");
	if (IS_ERR(priv->mclk) && PTR_ERR(priv->mclk) != -ENOENT) {
@@ -445,10 +564,6 @@ static int tas571x_i2c_probe(struct i2c_client *client,
	if (ret)
		return ret;

	ret = regmap_update_bits(priv->regmap, TAS571X_SYS_CTRL_2_REG,
				 TAS571X_SYS_CTRL_2_SDN_MASK, 0);
	if (ret)
		return ret;

	memcpy(&priv->codec_driver, &tas571x_codec, sizeof(priv->codec_driver));
	priv->codec_driver.controls = priv->chip->controls;
@@ -486,14 +601,16 @@ static const struct of_device_id tas571x_of_match[] = {
	{ .compatible = "ti,tas5711", .data = &tas5711_chip, },
	{ .compatible = "ti,tas5717", .data = &tas5717_chip, },
	{ .compatible = "ti,tas5719", .data = &tas5717_chip, },
	{ .compatible = "ti,tas5721", .data = &tas5721_chip, },
	{ }
};
MODULE_DEVICE_TABLE(of, tas571x_of_match);

static const struct i2c_device_id tas571x_i2c_id[] = {
	{ "tas5711", 0 },
	{ "tas5717", 0 },
	{ "tas5719", 0 },
	{ "tas5711", (kernel_ulong_t) &tas5711_chip },
	{ "tas5717", (kernel_ulong_t) &tas5717_chip },
	{ "tas5719", (kernel_ulong_t) &tas5717_chip },
	{ "tas5721", (kernel_ulong_t) &tas5721_chip },
	{ }
};
MODULE_DEVICE_TABLE(i2c, tas571x_i2c_id);
Loading