Browse Source

Merge remote-tracking branches 'asoc/topic/tas2552', 'asoc/topic/tas5720', 'asoc/topic/tegra', 'asoc/topic/tlv320aic32x4' and 'asoc/topic/tlv320aic3x' into asoc-next

Mark Brown 8 years ago

+ 12 - 1
Documentation/devicetree/bindings/sound/tlv320aic32x4.txt

@@ -3,7 +3,9 @@ Texas Instruments - tlv320aic32x4 Codec module
 The tlv320aic32x4 serial control bus communicates through I2C protocols
 The tlv320aic32x4 serial control bus communicates through I2C protocols
 
 
 Required properties:
 Required properties:
- - compatible: Should be "ti,tlv320aic32x4"
+ - compatible - "string" - One of:
+	"ti,tlv320aic32x4" TLV320AIC3204
+	"ti,tlv320aic32x6" TLV320AIC3206, TLV320AIC3256
  - reg: I2C slave address
  - reg: I2C slave address
  - supply-*: Required supply regulators are:
  - supply-*: Required supply regulators are:
     "iov" - digital IO power supply
     "iov" - digital IO power supply
@@ -18,6 +20,8 @@ Optional properties:
  - reset-gpios: Reset-GPIO phandle with args as described in gpio/gpio.txt
  - reset-gpios: Reset-GPIO phandle with args as described in gpio/gpio.txt
  - clocks/clock-names: Clock named 'mclk' for the master clock of the codec.
  - clocks/clock-names: Clock named 'mclk' for the master clock of the codec.
    See clock/clock-bindings.txt for information about the detailed format.
    See clock/clock-bindings.txt for information about the detailed format.
+ - aic32x4-gpio-func - <array of 5 int>
+	- Types are defined in include/sound/tlv320aic32x4.h
 
 
 
 
 Example:
 Example:
@@ -27,4 +31,11 @@ codec: tlv320aic32x4@18 {
 	reg = <0x18>;
 	reg = <0x18>;
 	clocks = <&clks 201>;
 	clocks = <&clks 201>;
 	clock-names = "mclk";
 	clock-names = "mclk";
+	aic32x4-gpio-func= <
+			0xff /* AIC32X4_MFPX_DEFAULT_VALUE */
+			0xff /* AIC32X4_MFPX_DEFAULT_VALUE */
+			0x04 /* MFP3 AIC32X4_MFP3_GPIO_ENABLED */
+			0xff /* AIC32X4_MFPX_DEFAULT_VALUE */
+			0x08 /* MFP5 AIC32X4_MFP5_GPIO_INPUT */
+		>;
 };
 };

+ 5 - 0
Documentation/devicetree/bindings/sound/tlv320aic3x.txt

@@ -26,6 +26,11 @@ Optional properties:
 	3 - MICBIAS output is connected to AVDD,
 	3 - MICBIAS output is connected to AVDD,
 	If this node is not mentioned or if the value is incorrect, then MicBias
 	If this node is not mentioned or if the value is incorrect, then MicBias
 	is powered down.
 	is powered down.
+- ai3x-ocmv - Output Common-Mode Voltage selection:
+	0 - 1.35V,
+	1 - 1.5V,
+	2 - 1.65V,
+	3 - 1.8V
 - AVDD-supply, IOVDD-supply, DRVDD-supply, DVDD-supply : power supplies for the
 - AVDD-supply, IOVDD-supply, DRVDD-supply, DVDD-supply : power supplies for the
   device as covered in Documentation/devicetree/bindings/regulator/regulator.txt
   device as covered in Documentation/devicetree/bindings/regulator/regulator.txt
 
 

+ 23 - 0
include/sound/tlv320aic32x4.h

@@ -22,7 +22,30 @@
 #define AIC32X4_MICPGA_ROUTE_LMIC_IN2R_10K	0x00000001
 #define AIC32X4_MICPGA_ROUTE_LMIC_IN2R_10K	0x00000001
 #define AIC32X4_MICPGA_ROUTE_RMIC_IN1L_10K	0x00000002
 #define AIC32X4_MICPGA_ROUTE_RMIC_IN1L_10K	0x00000002
 
 
+/* GPIO API */
+#define AIC32X4_MFPX_DEFAULT_VALUE	0xff
+
+#define AIC32X4_MFP1_DIN_DISABLED	0
+#define AIC32X4_MFP1_DIN_ENABLED	0x2
+#define AIC32X4_MFP1_GPIO_IN		0x4
+
+#define AIC32X4_MFP2_GPIO_OUT_LOW	0x0
+#define AIC32X4_MFP2_GPIO_OUT_HIGH	0x1
+
+#define AIC32X4_MFP_GPIO_ENABLED	0x4
+
+#define AIC32X4_MFP5_GPIO_DISABLED	0x0
+#define AIC32X4_MFP5_GPIO_INPUT		0x8
+#define AIC32X4_MFP5_GPIO_OUTPUT	0xc
+#define AIC32X4_MFP5_GPIO_OUT_LOW	0x0
+#define AIC32X4_MFP5_GPIO_OUT_HIGH	0x1
+
+struct aic32x4_setup_data {
+	unsigned int gpio_func[5];
+};
+
 struct aic32x4_pdata {
 struct aic32x4_pdata {
+	struct aic32x4_setup_data *setup;
 	u32 power_cfg;
 	u32 power_cfg;
 	u32 micpga_routing;
 	u32 micpga_routing;
 	bool swapdacs;
 	bool swapdacs;

+ 7 - 4
sound/soc/codecs/tas2552.c

@@ -192,7 +192,7 @@ static int tas2552_setup_pll(struct snd_soc_codec *codec,
 		 * pll_clk = (.5 * pll_clkin * J.D) / 2^p
 		 * pll_clk = (.5 * pll_clkin * J.D) / 2^p
 		 * Need to fill in J and D here based on incoming freq
 		 * Need to fill in J and D here based on incoming freq
 		 */
 		 */
-		unsigned int d;
+		unsigned int d, q, t;
 		u8 j;
 		u8 j;
 		u8 pll_sel = (tas2552->pll_clk_id << 3) & TAS2552_PLL_SRC_MASK;
 		u8 pll_sel = (tas2552->pll_clk_id << 3) & TAS2552_PLL_SRC_MASK;
 		u8 p = snd_soc_read(codec, TAS2552_PLL_CTRL_1);
 		u8 p = snd_soc_read(codec, TAS2552_PLL_CTRL_1);
@@ -200,9 +200,12 @@ static int tas2552_setup_pll(struct snd_soc_codec *codec,
 		p = (p >> 7);
 		p = (p >> 7);
 
 
 recalc:
 recalc:
-		j = (pll_clk * 2 * (1 << p)) / pll_clkin;
-		d = (pll_clk * 2 * (1 << p)) % pll_clkin;
-		d /= (pll_clkin / 10000);
+		t = (pll_clk * 2) << p;
+		j = t / pll_clkin;
+		d = t % pll_clkin;
+		t = pll_clkin / 10000;
+		q = d / (t + 1);
+		d = q + ((9999 - pll_clkin % 10000) * (d / t - q)) / 10000;
 
 
 		if (d && (pll_clkin < 512000 || pll_clkin > 9200000)) {
 		if (d && (pll_clkin < 512000 || pll_clkin > 9200000)) {
 			if (tas2552->pll_clk_id == TAS2552_PLL_CLKIN_BCLK) {
 			if (tas2552->pll_clk_id == TAS2552_PLL_CLKIN_BCLK) {

+ 2 - 0
sound/soc/codecs/tlv320aic32x4-i2c.c

@@ -47,12 +47,14 @@ static int aic32x4_i2c_remove(struct i2c_client *i2c)
 
 
 static const struct i2c_device_id aic32x4_i2c_id[] = {
 static const struct i2c_device_id aic32x4_i2c_id[] = {
 	{ "tlv320aic32x4", 0 },
 	{ "tlv320aic32x4", 0 },
+	{ "tlv320aic32x6", 1 },
 	{ /* sentinel */ }
 	{ /* sentinel */ }
 };
 };
 MODULE_DEVICE_TABLE(i2c, aic32x4_i2c_id);
 MODULE_DEVICE_TABLE(i2c, aic32x4_i2c_id);
 
 
 static const struct of_device_id aic32x4_of_id[] = {
 static const struct of_device_id aic32x4_of_id[] = {
 	{ .compatible = "ti,tlv320aic32x4", },
 	{ .compatible = "ti,tlv320aic32x4", },
+	{ .compatible = "ti,tlv320aic32x6", },
 	{ /* senitel */ }
 	{ /* senitel */ }
 };
 };
 MODULE_DEVICE_TABLE(of, aic32x4_of_id);
 MODULE_DEVICE_TABLE(of, aic32x4_of_id);

+ 2 - 0
sound/soc/codecs/tlv320aic32x4-spi.c

@@ -48,12 +48,14 @@ static int aic32x4_spi_remove(struct spi_device *spi)
 
 
 static const struct spi_device_id aic32x4_spi_id[] = {
 static const struct spi_device_id aic32x4_spi_id[] = {
 	{ "tlv320aic32x4", 0 },
 	{ "tlv320aic32x4", 0 },
+	{ "tlv320aic32x6", 1 },
 	{ /* sentinel */ }
 	{ /* sentinel */ }
 };
 };
 MODULE_DEVICE_TABLE(spi, aic32x4_spi_id);
 MODULE_DEVICE_TABLE(spi, aic32x4_spi_id);
 
 
 static const struct of_device_id aic32x4_of_id[] = {
 static const struct of_device_id aic32x4_of_id[] = {
 	{ .compatible = "ti,tlv320aic32x4", },
 	{ .compatible = "ti,tlv320aic32x4", },
+	{ .compatible = "ti,tlv320aic32x6", },
 	{ /* senitel */ }
 	{ /* senitel */ }
 };
 };
 MODULE_DEVICE_TABLE(of, aic32x4_of_id);
 MODULE_DEVICE_TABLE(of, aic32x4_of_id);

+ 206 - 0
sound/soc/codecs/tlv320aic32x4.c

@@ -74,6 +74,152 @@ struct aic32x4_priv {
 	struct regulator *supply_iov;
 	struct regulator *supply_iov;
 	struct regulator *supply_dv;
 	struct regulator *supply_dv;
 	struct regulator *supply_av;
 	struct regulator *supply_av;
+
+	struct aic32x4_setup_data *setup;
+	struct device *dev;
+};
+
+static int aic32x4_get_mfp1_gpio(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	u8 val;
+
+	val = snd_soc_read(codec, AIC32X4_DINCTL);
+
+	ucontrol->value.integer.value[0] = (val & 0x01);
+
+	return 0;
+};
+
+static int aic32x4_set_mfp2_gpio(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	u8 val;
+	u8 gpio_check;
+
+	val = snd_soc_read(codec, AIC32X4_DOUTCTL);
+	gpio_check = (val & AIC32X4_MFP_GPIO_ENABLED);
+	if (gpio_check != AIC32X4_MFP_GPIO_ENABLED) {
+		printk(KERN_ERR "%s: MFP2 is not configure as a GPIO output\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	if (ucontrol->value.integer.value[0] == (val & AIC32X4_MFP2_GPIO_OUT_HIGH))
+		return 0;
+
+	if (ucontrol->value.integer.value[0])
+		val |= ucontrol->value.integer.value[0];
+	else
+		val &= ~AIC32X4_MFP2_GPIO_OUT_HIGH;
+
+	snd_soc_write(codec, AIC32X4_DOUTCTL, val);
+
+	return 0;
+};
+
+static int aic32x4_get_mfp3_gpio(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	u8 val;
+
+	val = snd_soc_read(codec, AIC32X4_SCLKCTL);
+
+	ucontrol->value.integer.value[0] = (val & 0x01);
+
+	return 0;
+};
+
+static int aic32x4_set_mfp4_gpio(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	u8 val;
+	u8 gpio_check;
+
+	val = snd_soc_read(codec, AIC32X4_MISOCTL);
+	gpio_check = (val & AIC32X4_MFP_GPIO_ENABLED);
+	if (gpio_check != AIC32X4_MFP_GPIO_ENABLED) {
+		printk(KERN_ERR "%s: MFP4 is not configure as a GPIO output\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	if (ucontrol->value.integer.value[0] == (val & AIC32X4_MFP5_GPIO_OUT_HIGH))
+		return 0;
+
+	if (ucontrol->value.integer.value[0])
+		val |= ucontrol->value.integer.value[0];
+	else
+		val &= ~AIC32X4_MFP5_GPIO_OUT_HIGH;
+
+	snd_soc_write(codec, AIC32X4_MISOCTL, val);
+
+	return 0;
+};
+
+static int aic32x4_get_mfp5_gpio(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	u8 val;
+
+	val = snd_soc_read(codec, AIC32X4_GPIOCTL);
+	ucontrol->value.integer.value[0] = ((val & 0x2) >> 1);
+
+	return 0;
+};
+
+static int aic32x4_set_mfp5_gpio(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	u8 val;
+	u8 gpio_check;
+
+	val = snd_soc_read(codec, AIC32X4_GPIOCTL);
+	gpio_check = (val & AIC32X4_MFP5_GPIO_OUTPUT);
+	if (gpio_check != AIC32X4_MFP5_GPIO_OUTPUT) {
+		printk(KERN_ERR "%s: MFP5 is not configure as a GPIO output\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	if (ucontrol->value.integer.value[0] == (val & 0x1))
+		return 0;
+
+	if (ucontrol->value.integer.value[0])
+		val |= ucontrol->value.integer.value[0];
+	else
+		val &= 0xfe;
+
+	snd_soc_write(codec, AIC32X4_GPIOCTL, val);
+
+	return 0;
+};
+
+static const struct snd_kcontrol_new aic32x4_mfp1[] = {
+	SOC_SINGLE_BOOL_EXT("MFP1 GPIO", 0, aic32x4_get_mfp1_gpio, NULL),
+};
+
+static const struct snd_kcontrol_new aic32x4_mfp2[] = {
+	SOC_SINGLE_BOOL_EXT("MFP2 GPIO", 0, NULL, aic32x4_set_mfp2_gpio),
+};
+
+static const struct snd_kcontrol_new aic32x4_mfp3[] = {
+	SOC_SINGLE_BOOL_EXT("MFP3 GPIO", 0, aic32x4_get_mfp3_gpio, NULL),
+};
+
+static const struct snd_kcontrol_new aic32x4_mfp4[] = {
+	SOC_SINGLE_BOOL_EXT("MFP4 GPIO", 0, NULL, aic32x4_set_mfp4_gpio),
+};
+
+static const struct snd_kcontrol_new aic32x4_mfp5[] = {
+	SOC_SINGLE_BOOL_EXT("MFP5 GPIO", 0, aic32x4_get_mfp5_gpio,
+		aic32x4_set_mfp5_gpio),
 };
 };
 
 
 /* 0dB min, 0.5dB steps */
 /* 0dB min, 0.5dB steps */
@@ -734,6 +880,52 @@ static struct snd_soc_dai_driver aic32x4_dai = {
 	.symmetric_rates = 1,
 	.symmetric_rates = 1,
 };
 };
 
 
+static void aic32x4_setup_gpios(struct snd_soc_codec *codec)
+{
+	struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
+
+	/* setup GPIO functions */
+	/* MFP1 */
+	if (aic32x4->setup->gpio_func[0] != AIC32X4_MFPX_DEFAULT_VALUE) {
+		snd_soc_write(codec, AIC32X4_DINCTL,
+		      aic32x4->setup->gpio_func[0]);
+		snd_soc_add_codec_controls(codec, aic32x4_mfp1,
+			ARRAY_SIZE(aic32x4_mfp1));
+	}
+
+	/* MFP2 */
+	if (aic32x4->setup->gpio_func[1] != AIC32X4_MFPX_DEFAULT_VALUE) {
+		snd_soc_write(codec, AIC32X4_DOUTCTL,
+		      aic32x4->setup->gpio_func[1]);
+		snd_soc_add_codec_controls(codec, aic32x4_mfp2,
+			ARRAY_SIZE(aic32x4_mfp2));
+	}
+
+	/* MFP3 */
+	if (aic32x4->setup->gpio_func[2] != AIC32X4_MFPX_DEFAULT_VALUE) {
+		snd_soc_write(codec, AIC32X4_SCLKCTL,
+		      aic32x4->setup->gpio_func[2]);
+		snd_soc_add_codec_controls(codec, aic32x4_mfp3,
+			ARRAY_SIZE(aic32x4_mfp3));
+	}
+
+	/* MFP4 */
+	if (aic32x4->setup->gpio_func[3] != AIC32X4_MFPX_DEFAULT_VALUE) {
+		snd_soc_write(codec, AIC32X4_MISOCTL,
+		      aic32x4->setup->gpio_func[3]);
+		snd_soc_add_codec_controls(codec, aic32x4_mfp4,
+			ARRAY_SIZE(aic32x4_mfp4));
+	}
+
+	/* MFP5 */
+	if (aic32x4->setup->gpio_func[4] != AIC32X4_MFPX_DEFAULT_VALUE) {
+		snd_soc_write(codec, AIC32X4_GPIOCTL,
+		      aic32x4->setup->gpio_func[4]);
+		snd_soc_add_codec_controls(codec, aic32x4_mfp5,
+			ARRAY_SIZE(aic32x4_mfp5));
+	}
+}
+
 static int aic32x4_codec_probe(struct snd_soc_codec *codec)
 static int aic32x4_codec_probe(struct snd_soc_codec *codec)
 {
 {
 	struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
 	struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
@@ -746,6 +938,9 @@ static int aic32x4_codec_probe(struct snd_soc_codec *codec)
 
 
 	snd_soc_write(codec, AIC32X4_RESET, 0x01);
 	snd_soc_write(codec, AIC32X4_RESET, 0x01);
 
 
+	if (aic32x4->setup)
+		aic32x4_setup_gpios(codec);
+
 	/* Power platform configuration */
 	/* Power platform configuration */
 	if (aic32x4->power_cfg & AIC32X4_PWR_MICBIAS_2075_LDOIN) {
 	if (aic32x4->power_cfg & AIC32X4_PWR_MICBIAS_2075_LDOIN) {
 		snd_soc_write(codec, AIC32X4_MICBIAS, AIC32X4_MICBIAS_LDOIN |
 		snd_soc_write(codec, AIC32X4_MICBIAS, AIC32X4_MICBIAS_LDOIN |
@@ -810,10 +1005,20 @@ static const struct snd_soc_codec_driver soc_codec_dev_aic32x4 = {
 static int aic32x4_parse_dt(struct aic32x4_priv *aic32x4,
 static int aic32x4_parse_dt(struct aic32x4_priv *aic32x4,
 		struct device_node *np)
 		struct device_node *np)
 {
 {
+	struct aic32x4_setup_data *aic32x4_setup;
+
+	aic32x4_setup = devm_kzalloc(aic32x4->dev, sizeof(*aic32x4_setup),
+							GFP_KERNEL);
+	if (!aic32x4_setup)
+		return -ENOMEM;
+
 	aic32x4->swapdacs = false;
 	aic32x4->swapdacs = false;
 	aic32x4->micpga_routing = 0;
 	aic32x4->micpga_routing = 0;
 	aic32x4->rstn_gpio = of_get_named_gpio(np, "reset-gpios", 0);
 	aic32x4->rstn_gpio = of_get_named_gpio(np, "reset-gpios", 0);
 
 
+	if (of_property_read_u32_array(np, "aic32x4-gpio-func",
+				aic32x4_setup->gpio_func, 5) >= 0)
+		aic32x4->setup = aic32x4_setup;
 	return 0;
 	return 0;
 }
 }
 
 
@@ -932,6 +1137,7 @@ int aic32x4_probe(struct device *dev, struct regmap *regmap)
 	if (aic32x4 == NULL)
 	if (aic32x4 == NULL)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
+	aic32x4->dev = dev;
 	dev_set_drvdata(dev, aic32x4);
 	dev_set_drvdata(dev, aic32x4);
 
 
 	if (pdata) {
 	if (pdata) {

+ 3 - 0
sound/soc/codecs/tlv320aic32x4.h

@@ -44,8 +44,11 @@ int aic32x4_remove(struct device *dev);
 #define AIC32X4_IFACE4		31
 #define AIC32X4_IFACE4		31
 #define AIC32X4_IFACE5		32
 #define AIC32X4_IFACE5		32
 #define AIC32X4_IFACE6		33
 #define AIC32X4_IFACE6		33
+#define AIC32X4_GPIOCTL		52
 #define AIC32X4_DOUTCTL		53
 #define AIC32X4_DOUTCTL		53
 #define AIC32X4_DINCTL		54
 #define AIC32X4_DINCTL		54
+#define AIC32X4_MISOCTL		55
+#define AIC32X4_SCLKCTL		56
 #define AIC32X4_DACSPB		60
 #define AIC32X4_DACSPB		60
 #define AIC32X4_ADCSPB		61
 #define AIC32X4_ADCSPB		61
 #define AIC32X4_DACSETUP	63
 #define AIC32X4_DACSETUP	63

+ 45 - 0
sound/soc/codecs/tlv320aic3x.c

@@ -93,6 +93,8 @@ struct aic3x_priv {
 
 
 	/* Selects the micbias voltage */
 	/* Selects the micbias voltage */
 	enum aic3x_micbias_voltage micbias_vg;
 	enum aic3x_micbias_voltage micbias_vg;
+	/* Output Common-Mode Voltage */
+	u8 ocmv;
 };
 };
 
 
 static const struct reg_default aic3x_reg[] = {
 static const struct reg_default aic3x_reg[] = {
@@ -1572,6 +1574,10 @@ static int aic3x_init(struct snd_soc_codec *codec)
 		break;
 		break;
 	}
 	}
 
 
+	/*  Output common-mode voltage = 1.5 V */
+	snd_soc_update_bits(codec, HPOUT_SC, HPOUT_SC_OCMV_MASK,
+			    aic3x->ocmv << HPOUT_SC_OCMV_SHIFT);
+
 	return 0;
 	return 0;
 }
 }
 
 
@@ -1699,6 +1705,43 @@ static const struct snd_soc_codec_driver soc_codec_dev_aic3x = {
 	},
 	},
 };
 };
 
 
+static void aic3x_configure_ocmv(struct i2c_client *client)
+{
+	struct device_node *np = client->dev.of_node;
+	struct aic3x_priv *aic3x = i2c_get_clientdata(client);
+	u32 value;
+	int dvdd, avdd;
+
+	if (np && !of_property_read_u32(np, "ai3x-ocmv", &value)) {
+		/* OCMV setting is forced by DT */
+		if (value <= 3) {
+			aic3x->ocmv = value;
+			return;
+		}
+	}
+
+	dvdd = regulator_get_voltage(aic3x->supplies[1].consumer);
+	avdd = regulator_get_voltage(aic3x->supplies[2].consumer);
+
+	if (avdd > 3600000 || dvdd > 1950000) {
+		dev_warn(&client->dev,
+			 "Too high supply voltage(s) AVDD: %d, DVDD: %d\n",
+			 avdd, dvdd);
+	} else if (avdd == 3600000 && dvdd == 1950000) {
+		aic3x->ocmv = HPOUT_SC_OCMV_1_8V;
+	} else if (avdd > 3300000 && dvdd > 1800000) {
+		aic3x->ocmv = HPOUT_SC_OCMV_1_65V;
+	} else if (avdd > 3000000 && dvdd > 1650000) {
+		aic3x->ocmv = HPOUT_SC_OCMV_1_5V;
+	} else if (avdd >= 2700000 && dvdd >= 1525000) {
+		aic3x->ocmv = HPOUT_SC_OCMV_1_35V;
+	} else {
+		dev_warn(&client->dev,
+			 "Invalid supply voltage(s) AVDD: %d, DVDD: %d\n",
+			 avdd, dvdd);
+	}
+}
+
 /*
 /*
  * AIC3X 2 wire address can be up to 4 devices with device addresses
  * AIC3X 2 wire address can be up to 4 devices with device addresses
  * 0x18, 0x19, 0x1A, 0x1B
  * 0x18, 0x19, 0x1A, 0x1B
@@ -1816,6 +1859,8 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
 		goto err_gpio;
 		goto err_gpio;
 	}
 	}
 
 
+	aic3x_configure_ocmv(i2c);
+
 	if (aic3x->model == AIC3X_MODEL_3007) {
 	if (aic3x->model == AIC3X_MODEL_3007) {
 		ret = regmap_register_patch(aic3x->regmap, aic3007_class_d,
 		ret = regmap_register_patch(aic3x->regmap, aic3007_class_d,
 					    ARRAY_SIZE(aic3007_class_d));
 					    ARRAY_SIZE(aic3007_class_d));

+ 8 - 0
sound/soc/codecs/tlv320aic3x.h

@@ -243,6 +243,14 @@
 #define MICBIAS_LEVEL_SHIFT	(6)
 #define MICBIAS_LEVEL_SHIFT	(6)
 #define MICBIAS_LEVEL_MASK	(3 << 6)
 #define MICBIAS_LEVEL_MASK	(3 << 6)
 
 
+/* HPOUT_SC */
+#define HPOUT_SC_OCMV_MASK	(3 << 6)
+#define HPOUT_SC_OCMV_SHIFT	(6)
+#define HPOUT_SC_OCMV_1_35V	0
+#define HPOUT_SC_OCMV_1_5V	1
+#define HPOUT_SC_OCMV_1_65V	2
+#define HPOUT_SC_OCMV_1_8V	3
+
 /* headset detection / button API */
 /* headset detection / button API */
 
 
 /* The AIC3x supports detection of stereo headsets (GND + left + right signal)
 /* The AIC3x supports detection of stereo headsets (GND + left + right signal)

+ 14 - 28
sound/soc/tegra/Kconfig

@@ -9,8 +9,8 @@ config SND_SOC_TEGRA
 	  Say Y or M here if you want support for SoC audio on Tegra.
 	  Say Y or M here if you want support for SoC audio on Tegra.
 
 
 config SND_SOC_TEGRA20_AC97
 config SND_SOC_TEGRA20_AC97
-	tristate
-	depends on SND_SOC_TEGRA && ARCH_TEGRA_2x_SOC
+	tristate "Tegra20 AC97 interface"
+	depends on SND_SOC_TEGRA
 	select SND_SOC_AC97_BUS
 	select SND_SOC_AC97_BUS
 	select SND_SOC_TEGRA20_DAS
 	select SND_SOC_TEGRA20_DAS
 	help
 	help
@@ -19,16 +19,16 @@ config SND_SOC_TEGRA20_AC97
 	  machine drivers to support below.
 	  machine drivers to support below.
 
 
 config SND_SOC_TEGRA20_DAS
 config SND_SOC_TEGRA20_DAS
-	tristate
-	depends on SND_SOC_TEGRA && ARCH_TEGRA_2x_SOC
+	tristate "Tegra20 DAS module"
+	depends on SND_SOC_TEGRA
 	help
 	help
 	  Say Y or M if you want to add support for the Tegra20 DAS module.
 	  Say Y or M if you want to add support for the Tegra20 DAS module.
 	  You will also need to select the individual machine drivers to
 	  You will also need to select the individual machine drivers to
 	  support below.
 	  support below.
 
 
 config SND_SOC_TEGRA20_I2S
 config SND_SOC_TEGRA20_I2S
-	tristate
-	depends on SND_SOC_TEGRA && ARCH_TEGRA_2x_SOC
+	tristate "Tegra20 I2S interface"
+	depends on SND_SOC_TEGRA
 	select SND_SOC_TEGRA20_DAS
 	select SND_SOC_TEGRA20_DAS
 	help
 	help
 	  Say Y or M if you want to add support for codecs attached to the
 	  Say Y or M if you want to add support for codecs attached to the
@@ -36,8 +36,8 @@ config SND_SOC_TEGRA20_I2S
 	  machine drivers to support below.
 	  machine drivers to support below.
 
 
 config SND_SOC_TEGRA20_SPDIF
 config SND_SOC_TEGRA20_SPDIF
-	tristate
-	depends on SND_SOC_TEGRA && ARCH_TEGRA_2x_SOC
+	tristate "Tegra20 SPDIF interface"
+	depends on SND_SOC_TEGRA
 	default m
 	default m
 	help
 	help
 	  Say Y or M if you want to add support for the Tegra20 SPDIF interface.
 	  Say Y or M if you want to add support for the Tegra20 SPDIF interface.
@@ -45,16 +45,16 @@ config SND_SOC_TEGRA20_SPDIF
 	  below.
 	  below.
 
 
 config SND_SOC_TEGRA30_AHUB
 config SND_SOC_TEGRA30_AHUB
-	tristate
-	depends on SND_SOC_TEGRA && ARCH_TEGRA_3x_SOC
+	tristate "Tegra30 AHUB module"
+	depends on SND_SOC_TEGRA
 	help
 	help
-	  Say Y or M if you want to add support for the Tegra20 AHUB module.
+	  Say Y or M if you want to add support for the Tegra30 AHUB module.
 	  You will also need to select the individual machine drivers to
 	  You will also need to select the individual machine drivers to
 	  support below.
 	  support below.
 
 
 config SND_SOC_TEGRA30_I2S
 config SND_SOC_TEGRA30_I2S
-	tristate
-	depends on SND_SOC_TEGRA && ARCH_TEGRA_3x_SOC
+	tristate "Tegra30 I2S interface"
+	depends on SND_SOC_TEGRA
 	select SND_SOC_TEGRA30_AHUB
 	select SND_SOC_TEGRA30_AHUB
 	help
 	help
 	  Say Y or M if you want to add support for codecs attached to the
 	  Say Y or M if you want to add support for codecs attached to the
@@ -64,8 +64,6 @@ config SND_SOC_TEGRA30_I2S
 config SND_SOC_TEGRA_RT5640
 config SND_SOC_TEGRA_RT5640
 	tristate "SoC Audio support for Tegra boards using an RT5640 codec"
 	tristate "SoC Audio support for Tegra boards using an RT5640 codec"
 	depends on SND_SOC_TEGRA && I2C && GPIOLIB
 	depends on SND_SOC_TEGRA && I2C && GPIOLIB
-	select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC
-	select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC
 	select SND_SOC_RT5640
 	select SND_SOC_RT5640
 	help
 	help
 	  Say Y or M here if you want to add support for SoC audio on Tegra
 	  Say Y or M here if you want to add support for SoC audio on Tegra
@@ -74,8 +72,6 @@ config SND_SOC_TEGRA_RT5640
 config SND_SOC_TEGRA_WM8753
 config SND_SOC_TEGRA_WM8753
 	tristate "SoC Audio support for Tegra boards using a WM8753 codec"
 	tristate "SoC Audio support for Tegra boards using a WM8753 codec"
 	depends on SND_SOC_TEGRA && I2C && GPIOLIB
 	depends on SND_SOC_TEGRA && I2C && GPIOLIB
-	select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC
-	select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC
 	select SND_SOC_WM8753
 	select SND_SOC_WM8753
 	help
 	help
 	  Say Y or M here if you want to add support for SoC audio on Tegra
 	  Say Y or M here if you want to add support for SoC audio on Tegra
@@ -84,8 +80,6 @@ config SND_SOC_TEGRA_WM8753
 config SND_SOC_TEGRA_WM8903
 config SND_SOC_TEGRA_WM8903
 	tristate "SoC Audio support for Tegra boards using a WM8903 codec"
 	tristate "SoC Audio support for Tegra boards using a WM8903 codec"
 	depends on SND_SOC_TEGRA && I2C && GPIOLIB
 	depends on SND_SOC_TEGRA && I2C && GPIOLIB
-	select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC
-	select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC
 	select SND_SOC_WM8903
 	select SND_SOC_WM8903
 	help
 	help
 	  Say Y or M here if you want to add support for SoC audio on Tegra
 	  Say Y or M here if you want to add support for SoC audio on Tegra
@@ -94,7 +88,7 @@ config SND_SOC_TEGRA_WM8903
 
 
 config SND_SOC_TEGRA_WM9712
 config SND_SOC_TEGRA_WM9712
 	tristate "SoC Audio support for Tegra boards using a WM9712 codec"
 	tristate "SoC Audio support for Tegra boards using a WM9712 codec"
-	depends on SND_SOC_TEGRA && ARCH_TEGRA_2x_SOC && GPIOLIB
+	depends on SND_SOC_TEGRA && GPIOLIB
 	select SND_SOC_TEGRA20_AC97
 	select SND_SOC_TEGRA20_AC97
 	select SND_SOC_WM9712
 	select SND_SOC_WM9712
 	help
 	help
@@ -104,7 +98,6 @@ config SND_SOC_TEGRA_WM9712
 config SND_SOC_TEGRA_TRIMSLICE
 config SND_SOC_TEGRA_TRIMSLICE
 	tristate "SoC Audio support for TrimSlice board"
 	tristate "SoC Audio support for TrimSlice board"
 	depends on SND_SOC_TEGRA && I2C
 	depends on SND_SOC_TEGRA && I2C
-	select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC
 	select SND_SOC_TLV320AIC23_I2C
 	select SND_SOC_TLV320AIC23_I2C
 	help
 	help
 	  Say Y or M here if you want to add support for SoC audio on the
 	  Say Y or M here if you want to add support for SoC audio on the
@@ -113,7 +106,6 @@ config SND_SOC_TEGRA_TRIMSLICE
 config SND_SOC_TEGRA_ALC5632
 config SND_SOC_TEGRA_ALC5632
 	tristate "SoC Audio support for Tegra boards using an ALC5632 codec"
 	tristate "SoC Audio support for Tegra boards using an ALC5632 codec"
 	depends on SND_SOC_TEGRA && I2C && GPIOLIB
 	depends on SND_SOC_TEGRA && I2C && GPIOLIB
-	select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC
 	select SND_SOC_ALC5632
 	select SND_SOC_ALC5632
 	help
 	help
 	  Say Y or M here if you want to add support for SoC audio on the
 	  Say Y or M here if you want to add support for SoC audio on the
@@ -122,8 +114,6 @@ config SND_SOC_TEGRA_ALC5632
 config SND_SOC_TEGRA_MAX98090
 config SND_SOC_TEGRA_MAX98090
 	tristate "SoC Audio support for Tegra boards using a MAX98090 codec"
 	tristate "SoC Audio support for Tegra boards using a MAX98090 codec"
 	depends on SND_SOC_TEGRA && I2C && GPIOLIB
 	depends on SND_SOC_TEGRA && I2C && GPIOLIB
-	select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC
-	select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC
 	select SND_SOC_MAX98090
 	select SND_SOC_MAX98090
 	help
 	help
 	  Say Y or M here if you want to add support for SoC audio on Tegra
 	  Say Y or M here if you want to add support for SoC audio on Tegra
@@ -132,8 +122,6 @@ config SND_SOC_TEGRA_MAX98090
 config SND_SOC_TEGRA_RT5677
 config SND_SOC_TEGRA_RT5677
 	tristate "SoC Audio support for Tegra boards using a RT5677 codec"
 	tristate "SoC Audio support for Tegra boards using a RT5677 codec"
 	depends on SND_SOC_TEGRA && I2C && GPIOLIB
 	depends on SND_SOC_TEGRA && I2C && GPIOLIB
-	select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC
-	select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC
 	select SND_SOC_RT5677
 	select SND_SOC_RT5677
 	help
 	help
 	  Say Y or M here if you want to add support for SoC audio on Tegra
 	  Say Y or M here if you want to add support for SoC audio on Tegra
@@ -142,8 +130,6 @@ config SND_SOC_TEGRA_RT5677
 config SND_SOC_TEGRA_SGTL5000
 config SND_SOC_TEGRA_SGTL5000
 	tristate "SoC Audio support for Tegra boards using a SGTL5000 codec"
 	tristate "SoC Audio support for Tegra boards using a SGTL5000 codec"
 	depends on SND_SOC_TEGRA && I2C && GPIOLIB
 	depends on SND_SOC_TEGRA && I2C && GPIOLIB
-	select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC
-	select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC
 	select SND_SOC_SGTL5000
 	select SND_SOC_SGTL5000
 	help
 	help
 	  Say Y or M here if you want to add support for SoC audio on Tegra
 	  Say Y or M here if you want to add support for SoC audio on Tegra

+ 2 - 2
sound/soc/tegra/tegra30_ahub.c

@@ -544,8 +544,8 @@ static int tegra30_ahub_probe(struct platform_device *pdev)
 					soc_data->mod_list_mask))
 					soc_data->mod_list_mask))
 			continue;
 			continue;
 
 
-		rst = reset_control_get(&pdev->dev,
-					configlink_mods[i].rst_name);
+		rst = reset_control_get_exclusive(&pdev->dev,
+						  configlink_mods[i].rst_name);
 		if (IS_ERR(rst)) {
 		if (IS_ERR(rst)) {
 			dev_err(&pdev->dev, "Can't get reset %s\n",
 			dev_err(&pdev->dev, "Can't get reset %s\n",
 				configlink_mods[i].rst_name);
 				configlink_mods[i].rst_name);

+ 1 - 1
sound/soc/tegra/tegra30_i2s.c

@@ -275,7 +275,7 @@ static int tegra30_i2s_probe(struct snd_soc_dai *dai)
 	return 0;
 	return 0;
 }
 }
 
 
-static struct snd_soc_dai_ops tegra30_i2s_dai_ops = {
+static const struct snd_soc_dai_ops tegra30_i2s_dai_ops = {
 	.set_fmt	= tegra30_i2s_set_fmt,
 	.set_fmt	= tegra30_i2s_set_fmt,
 	.hw_params	= tegra30_i2s_hw_params,
 	.hw_params	= tegra30_i2s_hw_params,
 	.trigger	= tegra30_i2s_trigger,
 	.trigger	= tegra30_i2s_trigger,

+ 0 - 1
sound/soc/tegra/tegra_alc5632.c

@@ -160,7 +160,6 @@ static int tegra_alc5632_probe(struct platform_device *pdev)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
 	card->dev = &pdev->dev;
 	card->dev = &pdev->dev;
-	platform_set_drvdata(pdev, card);
 	snd_soc_card_set_drvdata(card, alc5632);
 	snd_soc_card_set_drvdata(card, alc5632);
 
 
 	alc5632->gpio_hp_det = of_get_named_gpio(np, "nvidia,hp-det-gpios", 0);
 	alc5632->gpio_hp_det = of_get_named_gpio(np, "nvidia,hp-det-gpios", 0);

+ 0 - 1
sound/soc/tegra/tegra_max98090.c

@@ -211,7 +211,6 @@ static int tegra_max98090_probe(struct platform_device *pdev)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
 	card->dev = &pdev->dev;
 	card->dev = &pdev->dev;
-	platform_set_drvdata(pdev, card);
 	snd_soc_card_set_drvdata(card, machine);
 	snd_soc_card_set_drvdata(card, machine);
 
 
 	machine->gpio_hp_det = of_get_named_gpio(np, "nvidia,hp-det-gpios", 0);
 	machine->gpio_hp_det = of_get_named_gpio(np, "nvidia,hp-det-gpios", 0);

+ 0 - 1
sound/soc/tegra/tegra_rt5640.c

@@ -161,7 +161,6 @@ static int tegra_rt5640_probe(struct platform_device *pdev)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
 	card->dev = &pdev->dev;
 	card->dev = &pdev->dev;
-	platform_set_drvdata(pdev, card);
 	snd_soc_card_set_drvdata(card, machine);
 	snd_soc_card_set_drvdata(card, machine);
 
 
 	machine->gpio_hp_det = of_get_named_gpio_flags(
 	machine->gpio_hp_det = of_get_named_gpio_flags(

+ 0 - 1
sound/soc/tegra/tegra_rt5677.c

@@ -204,7 +204,6 @@ static int tegra_rt5677_probe(struct platform_device *pdev)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
 	card->dev = &pdev->dev;
 	card->dev = &pdev->dev;
-	platform_set_drvdata(pdev, card);
 	snd_soc_card_set_drvdata(card, machine);
 	snd_soc_card_set_drvdata(card, machine);
 
 
 	machine->gpio_hp_det = of_get_named_gpio(np, "nvidia,hp-det-gpios", 0);
 	machine->gpio_hp_det = of_get_named_gpio(np, "nvidia,hp-det-gpios", 0);

+ 0 - 1
sound/soc/tegra/tegra_sgtl5000.c

@@ -124,7 +124,6 @@ static int tegra_sgtl5000_driver_probe(struct platform_device *pdev)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
 	card->dev = &pdev->dev;
 	card->dev = &pdev->dev;
-	platform_set_drvdata(pdev, card);
 	snd_soc_card_set_drvdata(card, machine);
 	snd_soc_card_set_drvdata(card, machine);
 
 
 	ret = snd_soc_of_parse_card_name(card, "nvidia,model");
 	ret = snd_soc_of_parse_card_name(card, "nvidia,model");

+ 0 - 1
sound/soc/tegra/tegra_wm8753.c

@@ -132,7 +132,6 @@ static int tegra_wm8753_driver_probe(struct platform_device *pdev)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
 	card->dev = &pdev->dev;
 	card->dev = &pdev->dev;
-	platform_set_drvdata(pdev, card);
 	snd_soc_card_set_drvdata(card, machine);
 	snd_soc_card_set_drvdata(card, machine);
 
 
 	ret = snd_soc_of_parse_card_name(card, "nvidia,model");
 	ret = snd_soc_of_parse_card_name(card, "nvidia,model");

+ 0 - 1
sound/soc/tegra/tegra_wm8903.c

@@ -246,7 +246,6 @@ static int tegra_wm8903_driver_probe(struct platform_device *pdev)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
 	card->dev = &pdev->dev;
 	card->dev = &pdev->dev;
-	platform_set_drvdata(pdev, card);
 	snd_soc_card_set_drvdata(card, machine);
 	snd_soc_card_set_drvdata(card, machine);
 
 
 	machine->gpio_spkr_en = of_get_named_gpio(np, "nvidia,spkr-en-gpios",
 	machine->gpio_spkr_en = of_get_named_gpio(np, "nvidia,spkr-en-gpios",

+ 0 - 1
sound/soc/tegra/tegra_wm9712.c

@@ -81,7 +81,6 @@ static int tegra_wm9712_driver_probe(struct platform_device *pdev)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
 	card->dev = &pdev->dev;
 	card->dev = &pdev->dev;
-	platform_set_drvdata(pdev, card);
 	snd_soc_card_set_drvdata(card, machine);
 	snd_soc_card_set_drvdata(card, machine);
 
 
 	machine->codec = platform_device_alloc("wm9712-codec", -1);
 	machine->codec = platform_device_alloc("wm9712-codec", -1);

+ 0 - 1
sound/soc/tegra/trimslice.c

@@ -127,7 +127,6 @@ static int tegra_snd_trimslice_probe(struct platform_device *pdev)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
 	card->dev = &pdev->dev;
 	card->dev = &pdev->dev;
-	platform_set_drvdata(pdev, card);
 	snd_soc_card_set_drvdata(card, trimslice);
 	snd_soc_card_set_drvdata(card, trimslice);
 
 
 	trimslice_tlv320aic23_dai.codec_of_node = of_parse_phandle(np,
 	trimslice_tlv320aic23_dai.codec_of_node = of_parse_phandle(np,