Asoc driver and device tree config for TAS5760 codec and spe... [chromiumos/third_party/kernel : chromeos-3.14]

455 views
Skip to first unread message

Sushain Razdan (Gerrit)

unread,
Apr 6, 2015, 6:07:14 AM4/6/15
to Olof Johansson
Sushain Razdan has uploaded a new change for review.

https://chromium-review.googlesource.com/264071

Change subject: Asoc driver and device tree config for TAS5760 codec and
speaker amplifier. Location: sound/soc/codec Initalises and configures the
chip with desired configuration and defines mixer controls as per Alsa's
control architecture. TEST: 1.Verified whether the
......................................................................

Asoc driver and device tree config for TAS5760 codec and speaker amplifier.
Location: sound/soc/codec
Initalises and configures the chip with desired configuration and defines
mixer controls as per Alsa's control architecture.
TEST:
1.Verified whether the desired config is set in the registers using
i2c-dev tools
2.Used Alsamixer utility for checking the volume changes in the amp
3.speaker-test to verify whether the device is able to playback with
desired volume settings and hw params.

Change-Id: I0385bf0dba0f736ddbf47bc27f4171618df04f37
---
A Documentation/devicetree/bindings/sound/tas5760.txt
M arch/mips/boot/dts/pistachio.dtsi
M arch/mips/boot/dts/pistachio_bub.dts
M chromeos/config/arm64/common.config
M chromeos/config/armel/common.config
M chromeos/config/mips/chromiumos-pistachio.flavour.config
M chromeos/config/x86_64/common.config
M sound/soc/codecs/Kconfig
M sound/soc/codecs/Makefile
A sound/soc/codecs/tas5760.c
A sound/soc/codecs/tas5760.h
11 files changed, 666 insertions(+), 1 deletion(-)



diff --git a/Documentation/devicetree/bindings/sound/tas5760.txt
b/Documentation/devicetree/bindings/sound/tas5760.txt
new file mode 100644
index 0000000..ddcc0ff
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/tas5760.txt
@@ -0,0 +1,46 @@
+Texas Instruments TAS5760 General purpose class-D amplifier.
+
+The codec is controlled through and I2C interface. It also has an optional
+speaker shutdown(SPK_SD) signal which can be wired to a GPIO.
+
+Required properties:
+
+- compatible: "ti, tas5760"
+- reg : The I2C address of the device
+- #sound-dai-cells: must be equal to 0
+
+Optional properties:
+
+- spk-sd-gpios: GPIO specifier for TAS5760's active low speaker shutdown
line
+- hw_params: subnode to specify the config parameters used for
initalisation
+ of chip. It consists of the following optional properties:
+ - pbtl-mode: selection for PBTL/BTL mode
+ - pbtl-right-channel: channel selection for PBTL mode
+ - volume-fading: enable/disable volume fading
+ - digital-clip: value for adjusting digital clip level
+ range: (0 to 0xFFFFF)
+ - digital-boost: digital gain of the amplifier
+ possible values(dB): 0,6,12,18
+ - analog-gain: value for adjusting analog gain of the amplifier
+ possible values(0.1 dBV): 192, 226, 250
+ - pwm-rate: control for pwm output swtching rate
+ range: (0 to 7)
+
+Example:
+ tas5760@06c {
+ compatible: "ti,tas5760";
+ reg = <0x6c>;
+ #sound-dai-cells = <0>;
+
+ spk-sd-gpios = <&gpio1 5 GPIO_ACTIVE_LOW>;
+
+ hw_params {
+ pbtl-mode;
+ pbtl-right-channel;
+ digital-clip = <0XFFFFF>;
+ volume-fading;
+ digital-boost = <6>;
+ analog-gain = <192>;
+ pwm-rate = <5>;
+ };
+ };
diff --git a/arch/mips/boot/dts/pistachio.dtsi
b/arch/mips/boot/dts/pistachio.dtsi
index 3705602..29be54c 100644
--- a/arch/mips/boot/dts/pistachio.dtsi
+++ b/arch/mips/boot/dts/pistachio.dtsi
@@ -11,6 +11,7 @@
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/interrupt-controller/mips-gic.h>
#include <dt-bindings/clock/pistachio-clk.h>
+#include <dt-bindings/gpio/gpio.h>

/ {
compatible = "img,pistachio";
diff --git a/arch/mips/boot/dts/pistachio_bub.dts
b/arch/mips/boot/dts/pistachio_bub.dts
index 11ab2fa..fe24008 100644
--- a/arch/mips/boot/dts/pistachio_bub.dts
+++ b/arch/mips/boot/dts/pistachio_bub.dts
@@ -31,6 +31,56 @@
regulator-max-microvolt = <1800000>;
regulator-boot-on;
};
+ sound {
+ compatible = "google,concerto-audio";
+ model = "Google Kennet";
+ clocks = <&clk_core CLK_AUDIO_PLL>, <&clk_core CLK_I2S>;
+ clock-names = "audio_pll", "mclk";
+ assigned-clocks = <&clk_core CLK_AUDIO_PLL_MUX>,
+ <&clk_core CLK_AUDIO_MUX>,
+ <&clk_core CLK_AUDIO_PLL>;
+ assigned-clock-parents = <&clk_core CLK_AUDIO_PLL>,
+ <&clk_core CLK_AUDIO_PLL_MUX>;
+ assigned-clock-rates = <0>, <0>, <147456000>;
+ pinctrl-0 = <&i2s_mclk_pin>;
+ pinctrl-names = "default";
+
+ img,cr-periph = <&cr_periph>;
+ img,cr-top = <&cr_top>;
+
+ i2s-out {
+ cpu {
+ sound-dai = <&i2s_out>;
+ format = "i2s";
+ bitclock-master;
+ frame-master;
+ };
+ codec-0 {
+ sound-dai = <&woofer>;
+ format = "i2s";
+ name-prefix = "Woofer";
+ };
+ codec-1 {
+ sound-dai = <&tweeter>;
+ format = "i2s";
+ name-prefix = "Tweeter";
+ };
+
+ };
+
+ i2s-in {
+ cpu {
+ sound-dai = <&i2s_in>;
+ format = "i2s";
+ };
+ };
+
+ parallel-out {
+ cpu {
+ sound-dai = <&parallel_out>;
+ };
+ };
+ };
};

&spfi1 {
@@ -102,9 +152,28 @@
clock-frequency = <400000>;
};

+
&i2c1 {
status = "okay";
clock-frequency = <400000>;
+
+ woofer: tas5760@6c {
+ compatible = "ti,tas5760";
+ reg = <0x6c>;
+ #sound-dai-cells = <0>;
+ hw-params {
+ volume-fading;
+ };
+ };
+ tweeter: tas5760@6d {
+ compatible = "ti,tas5760";
+ reg = <0x6d>;
+ #sound-dai-cells = <0>;
+ hw-params {
+ volume-fading;
+ };
+
+ };
};

&i2c2 {
@@ -116,3 +185,14 @@
status = "okay";
clock-frequency = <400000>;
};
+&i2s_out {
+ status = "okay";
+};
+
+&i2s_in {
+ status = "okay";
+};
+
+&parallel_out {
+ status = "okay";
+};
diff --git a/chromeos/config/arm64/common.config
b/chromeos/config/arm64/common.config
index f33b4c28..affa4dc 100644
--- a/chromeos/config/arm64/common.config
+++ b/chromeos/config/arm64/common.config
@@ -939,6 +939,7 @@
CONFIG_SND_SOC_RT5677_SPI=m
CONFIG_SND_SOC_SSM4567=m
# CONFIG_SND_SOC_TAS571X is not set
+# CONFIG_SND_SOC_TAS5760 is not set
CONFIG_SND_SOC_TEGRA=y
CONFIG_SND_SOC_TEGRA30_AHUB=m
CONFIG_SND_SOC_TEGRA30_I2S=m
diff --git a/chromeos/config/armel/common.config
b/chromeos/config/armel/common.config
index 927bee3..ba5b8ad 100644
--- a/chromeos/config/armel/common.config
+++ b/chromeos/config/armel/common.config
@@ -481,6 +481,7 @@
# CONFIG_SND_SOC_RT5677_SPI is not set
# CONFIG_SND_SOC_SSM4567 is not set
# CONFIG_SND_SOC_TAS571X is not set
+# CONFIG_SND_SOC_TAS5760 is not set
CONFIG_SND_TIMER=y
# CONFIG_SOC_AM33XX is not set
# CONFIG_SOC_AM43XX is not set
diff --git a/chromeos/config/mips/chromiumos-pistachio.flavour.config
b/chromeos/config/mips/chromiumos-pistachio.flavour.config
index 9827dae..eb7b3ae 100644
--- a/chromeos/config/mips/chromiumos-pistachio.flavour.config
+++ b/chromeos/config/mips/chromiumos-pistachio.flavour.config
@@ -453,7 +453,8 @@
# CONFIG_SND_SOC_QCOM is not set
# CONFIG_SND_SOC_RT5677_SPI is not set
# CONFIG_SND_SOC_SSM4567 is not set
-CONFIG_SND_SOC_TAS571X=y
+# CONFIG_SND_SOC_TAS571X is not set
+CONFIG_SND_SOC_TAS5760=y
# CONFIG_SND_SOC_TS3A227E is not set
CONFIG_SND_TIMER=y
CONFIG_SOC_IMG=y
diff --git a/chromeos/config/x86_64/common.config
b/chromeos/config/x86_64/common.config
index 50f55c6..7c891cf 100644
--- a/chromeos/config/x86_64/common.config
+++ b/chromeos/config/x86_64/common.config
@@ -1605,6 +1605,7 @@
CONFIG_SND_SOC_RT5677_SPI=m
# CONFIG_SND_SOC_SSM4567 is not set
# CONFIG_SND_SOC_TAS571X is not set
+# CONFIG_SND_SOC_TAS5760 is not set
# CONFIG_SND_SOC_TS3A227E is not set
# CONFIG_SND_SONICVIBES is not set
CONFIG_SND_TIMER=y
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 7da7cfb..806240b 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -77,6 +77,7 @@
select SND_SOC_STAC9766 if SND_SOC_AC97_BUS
select SND_SOC_TAS5086 if I2C
select SND_SOC_TAS571X if I2C
+ select SND_SOC_TAS5760 if I2C
select SND_SOC_TLV320AIC23 if I2C
select SND_SOC_TLV320AIC26 if SPI_MASTER
select SND_SOC_TLV320AIC32X4 if I2C
@@ -392,6 +393,10 @@
tristate "Texas Instruments TAS5711/TAS5717/TAS5719 power amplifiers"
depends on I2C

+config SND_SOC_TAS5760
+ tristate "Texas Instruments TAS5760 general purpose class-D
amplifier"
+ depends on I2C
+
config SND_SOC_TLV320AIC23
tristate

diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 5debf30..5a75d2b 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -70,6 +70,7 @@
snd-soc-stac9766-objs := stac9766.o
snd-soc-tas5086-objs := tas5086.o
snd-soc-tas571x-objs := tas571x.o
+snd-soc-tas5760-objs := tas5760.o
snd-soc-tlv320aic23-objs := tlv320aic23.o
snd-soc-tlv320aic26-objs := tlv320aic26.o
snd-soc-tlv320aic3x-objs := tlv320aic3x.o
@@ -209,6 +210,7 @@
obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o
obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o
obj-$(CONFIG_SND_SOC_TAS571X) += snd-soc-tas571x.o
+obj-$(CONFIG_SND_SOC_TAS5760) += snd-soc-tas5760.o
obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o
obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o
obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o
diff --git a/sound/soc/codecs/tas5760.c b/sound/soc/codecs/tas5760.c
new file mode 100644
index 0000000..c8455a0
--- /dev/null
+++ b/sound/soc/codecs/tas5760.c
@@ -0,0 +1,465 @@
+/*
+ * TAS5760 ASoC speaker amplifier driver
+ *
+ * Copyright (c) 2015 Imagination Technolgies Inc
+ *
+ * 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 (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#define DEBUG
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+
+#include "tas5760.h"
+
+
+struct tas5760_hw_params {
+ bool pbtl_mode;
+ bool pbtl_right_channel;
+ bool volume_fading;
+ unsigned int digital_clip;
+ unsigned int digital_boost;
+ unsigned int analog_gain;
+ unsigned int pwm_rate;
+};
+
+struct tas5760_private {
+ struct regmap *regmap;
+ unsigned int format;
+ struct tas5760_hw_params hw_params;
+ struct gpio_desc *spk_sd_gpio;
+};
+
+static bool tas5760_accessible_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case 0x07:
+ case 0x09 ... 0x0F:
+ return false;
+ default:
+ return true;
+ }
+}
+
+static bool tas5760_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case TAS5760_DEVICE_ID:
+ case TAS5760_ERR_STATUS:
+ return true;
+ }
+
+ return false;
+}
+static bool tas5760_writeable_reg(struct device *dev, unsigned int reg)
+{
+ return tas5760_accessible_reg(dev, reg) &&
+ !tas5760_volatile_reg(dev, reg);
+}
+
+
+static int tas5760_set_sysclk(struct snd_soc_dai *dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct device *dev = dai->codec->dev;
+
+ dev_dbg(dev, "clkid:%d, freq:%d, dir:%d", clk_id, freq, dir);
+ return 0;
+}
+
+static int tas5760_set_dai_fmt(struct snd_soc_dai *dai, unsigned int
format)
+{
+ struct tas5760_private *priv = snd_soc_codec_get_drvdata(dai->codec);
+ struct device *dev = dai->codec->dev;
+
+ dev_dbg(dev, "format:%d\n", format);
+ priv->format = format;
+
+ return 0;
+}
+
+static int tas5760_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ return 0;
+}
+
+static int tas5760_digital_mute(struct snd_soc_dai *dai, int mute)
+{
+ struct tas5760_private *priv = snd_soc_codec_get_drvdata(dai->codec);
+
+ return regmap_update_bits(priv->regmap,
+ TAS5760_VOL_CTRL,
+ TAS5760_MUTE_MASK,
+ mute ? TAS5760_MUTE_MASK : 0);
+}
+
+static int tas5760_init(struct device *dev, struct tas5760_private *priv)
+{
+
+ struct device_node *np = dev->of_node;
+ struct device_node *hw_config = of_get_child_by_name(np, "hw-params");
+ int ret, val;
+
+ if (!hw_config)
+ dev_warn(dev, "No hardware config for init: %ld\n",
+ PTR_ERR(hw_config));
+ else {
+
+ /* Mute the Device */
+ ret = regmap_update_bits(priv->regmap,
+ TAS5760_VOL_CTRL,
+ TAS5760_MUTE_MASK, TAS5760_MUTE_MASK);
+
+ /* BTL/PBTL mode configuration */
+ priv->hw_params.pbtl_mode = of_property_read_bool(hw_config,
+ "pbtl-mode");
+ dev_dbg(dev, "pbtl mode:%d\n", priv->hw_params.pbtl_mode);
+
+ /* Channel Selection for PBTL mode */
+ priv->hw_params.pbtl_right_channel = of_property_read_bool(
+ hw_config, "pbtl-right-channel");
+ dev_dbg(dev, "pbtl right channel:%d\n",
+ priv->hw_params.pbtl_right_channel);
+
+ ret = regmap_update_bits(priv->regmap, TAS5760_ANALOG_CTRL,
+ TAS5760_PBTL_MASK,
+ TAS5760_PBTL_EN_VAL(priv->hw_params.pbtl_mode) |
+ TAS5760_PBTL_CH_VAL(priv->hw_params.pbtl_right_channel));
+ if (ret < 0)
+ return ret;
+
+ /* Volume Fading */
+ priv->hw_params.volume_fading = of_property_read_bool(hw_config,
+ "volume-fading");
+ dev_dbg(dev, "volume fading:%d\n", priv->hw_params.volume_fading);
+ ret = regmap_update_bits(priv->regmap, TAS5760_VOL_CTRL,
+ TAS5760_VOL_FADE_MASK,
+ TAS5760_VOL_FADE_VAL(priv->hw_params.volume_fading));
+ if (ret < 0)
+ return ret;
+
+ /* Digital Clip level */
+ if (of_property_read_u32(hw_config, "digital-clip",
+ &priv->hw_params.digital_clip) == 0) {
+ if (priv->hw_params.digital_clip > TAS5760_DIGITAL_CLIP_MAX_VAL) {
+ dev_err(dev, "Invalid value for digital clip\n");
+ priv->hw_params.digital_clip = 0;
+ return -EINVAL;
+ }
+ dev_dbg(dev, "digital clip:%d\n", priv->hw_params.digital_clip);
+ ret = regmap_update_bits(priv->regmap, TAS5760_DIGITAL_CLIP_CTRL1,
+ TAS5760_DIGITAL_CLIP_MASK,
+ TAS5760_DIGITAL_CLIP1_VAL(priv->hw_params.digital_clip));
+ if (ret < 0)
+ return ret;
+
+ ret = regmap_write(priv->regmap, TAS5760_DIGITAL_CLIP_CTRL2,
+ TAS5760_DIGITAL_CLIP2_VAL(priv->hw_params.digital_clip));
+ if (ret < 0)
+ return ret;
+
+ ret = regmap_update_bits(priv->regmap, TAS5760_POWER_CTRL,
+ TAS5760_DIGITAL_CLIP_MASK,
+ TAS5760_DIGITAL_CLIP3_VAL(priv->hw_params.digital_clip));
+ if (ret < 0)
+ return ret;
+ }
+ /* Digital Boost */
+ if (of_property_read_u32(hw_config, "digital-boost",
+ &priv->hw_params.digital_boost) == 0) {
+ dev_dbg(dev, "digital boost:%d\n",
+ priv->hw_params.digital_boost);
+ switch (priv->hw_params.digital_boost) {
+ /* Values in dB */
+ case 0:
+ val = 0x00;
+ break;
+ case 6:
+ val = 0x01;
+ break;
+ case 12:
+ val = 0x02;
+ break;
+ case 18:
+ val = 0x03;
+ break;
+ default:
+ dev_err(dev, "Invalid value for digital-boost\n");
+ priv->hw_params.digital_boost = 0;
+ return -EINVAL;
+ }
+ ret = regmap_update_bits(priv->regmap, TAS5760_DIGITAL_CTRL,
+ TAS5760_DIGITAL_BOOST_MASK,
+ TAS5760_DIGITAL_BOOST_VAL(val));
+ if (ret < 0)
+ return ret;
+ }
+ /* Analog gain */
+ if (of_property_read_u32(hw_config, "analog-gain",
+ &priv->hw_params.analog_gain) == 0) {
+ dev_dbg(dev, "analog gain:%d\n",
+ priv->hw_params.analog_gain);
+ switch (priv->hw_params.analog_gain) {
+ /* Values in 0.1 dBV*/
+ case 192:
+ val = 0x0;
+ break;
+ case 226:
+ val = 0x01;
+ break;
+ case 250:
+ val = 0x02;
+ break;
+ default:
+ dev_err(dev, "Invalid value for analog gain\n");
+ priv->hw_params.analog_gain = 0;
+ return -EINVAL;
+ }
+ ret = regmap_update_bits(priv->regmap, TAS5760_ANALOG_CTRL,
+ TAS5760_ANALOG_GAIN_MASK,
+ TAS5760_ANALOG_GAIN_VAL(val));
+ if (ret < 0)
+ return ret;
+ }
+ /* PWM rate */
+ if (of_property_read_u32(hw_config, "pwm-rate",
+ &priv->hw_params.pwm_rate) == 0) {
+ if (priv->hw_params.pwm_rate > TAS5760_PWM_RATE_MAX) {
+ priv->hw_params.pwm_rate = 0;
+ return -EINVAL;
+ }
+ dev_dbg(dev, "pwm rate:%02x\n", priv->hw_params.pwm_rate);
+ ret = regmap_update_bits(priv->regmap, TAS5760_ANALOG_CTRL,
+ TAS5760_PWM_RATE_MASK,
+ TAS5760_PWM_RATE_VAL(priv->hw_params.pwm_rate));
+ if (ret < 0)
+ return ret;
+ }
+ /* Unmute the device */
+ ret = regmap_update_bits(priv->regmap,
+ TAS5760_VOL_CTRL,
+ TAS5760_MUTE_MASK, 0);
+ if (ret < 0)
+ return ret;
+ }
+
+ if (!IS_ERR(priv->spk_sd_gpio))
+ /* Enable the speaker amplifier */
+ gpiod_set_value(priv->spk_sd_gpio, 1);
+ else {
+ ret = regmap_update_bits(priv->regmap, TAS5760_POWER_CTRL,
+ TAS5760_SPK_SD_MASK,
+ TAS5760_SPK_SD_MASK);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct i2c_device_id tas5760_i2c_id[] = {
+ { "tas5760", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, tas5760_i2c_id);
+
+#ifdef CONFIG_OF
+static const struct of_device_id tas5760_dt_ids[] = {
+ { .compatible = "ti,tas5760", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, tas5760_dt_ids);
+#endif
+
+static int tas5760_probe(struct snd_soc_codec *codec)
+{
+ struct tas5760_private *priv = snd_soc_codec_get_drvdata(codec);
+ int ret = 0;
+
+ ret = tas5760_init(codec->dev, priv);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int tas5760_remove(struct snd_soc_codec *codec)
+{
+ struct tas5760_private *priv = snd_soc_codec_get_drvdata(codec);
+ int ret;
+ /* Mute the Device */
+ ret = regmap_update_bits(priv->regmap,
+ TAS5760_VOL_CTRL,
+ TAS5760_MUTE_MASK,
+ TAS5760_MUTE_MASK);
+ if (ret < 0)
+ return ret;
+
+ /* Put the device in shutdown */
+ if (!IS_ERR(priv->spk_sd_gpio))
+ gpiod_set_value(priv->spk_sd_gpio, 0);
+ else {
+ ret = regmap_update_bits(priv->regmap,
+ TAS5760_POWER_CTRL,
+ TAS5760_SPK_SD_MASK,
+ 0);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+};
+
+/* TAS5760 controls */
+static const DECLARE_TLV_DB_SCALE(tas5760_dac_tlv, -10350, 50, 1);
+
+static const struct snd_kcontrol_new tas5760_controls[] = {
+ SOC_DOUBLE_R_TLV("Channel 1/2 Playback Volume",
+ TAS5760_VOL_CTRL_L, TAS5760_VOL_CTRL_R,
+ 0, 0xff, 0, tas5760_dac_tlv),
+};
+
+static struct snd_soc_codec_driver soc_codec_dev_tas5760 = {
+ .probe = tas5760_probe,
+ .remove = tas5760_remove,
+ .controls = tas5760_controls,
+ .num_controls = ARRAY_SIZE(tas5760_controls),
+};
+
+
+static const struct snd_soc_dai_ops tas5760_dai_ops = {
+ .set_sysclk = tas5760_set_sysclk,
+ .set_fmt = tas5760_set_dai_fmt,
+ .hw_params = tas5760_hw_params,
+ .digital_mute = tas5760_digital_mute,
+};
+
+
+static const struct regmap_config tas5760_regmap = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = TAS5760_MAX_REG,
+ .cache_type = REGCACHE_RBTREE,
+ .volatile_reg = tas5760_volatile_reg,
+ .writeable_reg = tas5760_writeable_reg,
+ .readable_reg = tas5760_accessible_reg,
+};
+
+static struct snd_soc_dai_driver tas5760_dai = {
+ .name = "tas5760-hifi",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_96000,
+ .formats = SNDRV_PCM_FMTBIT_S24_LE |
+ SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S18_3LE |
+ SNDRV_PCM_FMTBIT_U20_3LE |
+ SNDRV_PCM_FMTBIT_S32_LE,
+ },
+ .ops = &tas5760_dai_ops,
+};
+
+
+static int tas5760_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct tas5760_private *priv;
+ struct device *dev = &client->dev;
+ int i = -1, ret;
+
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ i2c_set_clientdata(client, priv);
+
+ /* Initalise the register maps for tas5760 */
+ priv->regmap = devm_regmap_init_i2c(client, &tas5760_regmap);
+ if (IS_ERR(priv->regmap)) {
+ ret = PTR_ERR(priv->regmap);
+ dev_err(&client->dev, "Failed to create regmap: %d\n", ret);
+ return ret;
+ }
+
+ /* Identify the device */
+ ret = regmap_read(priv->regmap, TAS5760_DEVICE_ID, &i);
+ if (ret < 0)
+ return ret;
+
+ if (i == 0x00)
+ dev_dbg(dev, "Identified TAS5760 codec chip\n");
+ else {
+ dev_err(dev, "TAS5760 codec could not be identified");
+ return -ENODEV;
+ }
+
+ /* Get the spk_sd gpio */
+ priv->spk_sd_gpio = devm_gpiod_get(dev, "spk-sd");
+ if (!IS_ERR(priv->spk_sd_gpio)) {
+ /* Set the direction as output */
+ gpiod_direction_output(priv->spk_sd_gpio, 1);
+ /* Keep the speaker amplifier in shutdown */
+ gpiod_set_value(priv->spk_sd_gpio, 0);
+ } else {
+
+ dev_warn(dev, "error requesting spk_sd_gpio: %ld\n",
+ PTR_ERR(priv->spk_sd_gpio));
+ /* Use the SPK_SD bit to shutdown */
+ ret = regmap_update_bits(priv->regmap, TAS5760_POWER_CTRL,
+ TAS5760_SPK_SD_MASK,
+ 0);
+ if (ret < 0)
+ return ret;
+ }
+ return snd_soc_register_codec(&client->dev, &soc_codec_dev_tas5760,
+ &tas5760_dai, 1);
+}
+
+static int tas5760_i2c_remove(struct i2c_client *client)
+{
+ snd_soc_unregister_codec(&client->dev);
+ return 0;
+}
+
+
+static struct i2c_driver tas5760_i2c_driver = {
+ .driver = {
+ .name = "tas5760",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(tas5760_dt_ids),
+ },
+ .id_table = tas5760_i2c_id,
+ .probe = tas5760_i2c_probe,
+ .remove = tas5760_i2c_remove,
+};
+
+
+module_i2c_driver(tas5760_i2c_driver);
+
+MODULE_AUTHOR("Imagination Technologies Pvt Ltd.");
+MODULE_DESCRIPTION("Texas Instruments TAS5760 ALSA SoC Codec Driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/tas5760.h b/sound/soc/codecs/tas5760.h
new file mode 100644
index 0000000..dcaa809
--- /dev/null
+++ b/sound/soc/codecs/tas5760.h
@@ -0,0 +1,62 @@
+/*
+ * TAS5760 speaker amplifier driver
+ *
+ * Copyright (C) 2015 Imagination Technologies, Inc.
+ *
+ * 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
+ * (at your option) any later version.
+ */
+
+
+#ifndef _SND_SOC_CODEC_TAS5760_H_
+#define _SND_SOC_CODEC_TAS5760_H_
+
+/* Register Address Map */
+#define TAS5760_DEVICE_ID 0x00
+#define TAS5760_POWER_CTRL 0x01
+#define TAS5760_DIGITAL_CTRL 0x02
+#define TAS5760_VOL_CTRL 0x03
+#define TAS5760_VOL_CTRL_L 0x04
+#define TAS5760_VOL_CTRL_R 0x05
+#define TAS5760_ANALOG_CTRL 0x06
+#define TAS5760_ERR_STATUS 0x08
+#define TAS5760_DIGITAL_CLIP_CTRL2 0x10
+#define TAS5760_DIGITAL_CLIP_CTRL1 0x11
+#define TAS5760_MAX_REG TAS5760_DIGITAL_CLIP_CTRL1
+
+/* Register bit values/masks */
+#define TAS5760_SPK_SD_MASK 0x01
+
+#define TAS5760_PBTL_EN_MASK 0x80
+#define TAS5760_PBTL_EN_VAL(val) ((val) << 7)
+#define TAS5760_PBTL_CH_VAL(val) ((val) << 1)
+#define TAS5760_PBTL_CH_MASK 0x02
+#define TAS5760_PBTL_MASK (TAS5760_PBTL_EN_MASK | TAS5760_PBTL_CH_MASK)
+
+#define TAS5760_VOL_FADE_MASK 0x80
+#define TAS5760_VOL_FADE_VAL(val) ((val) << 7)
+
+#define TAS5760_MUTE_L_MASK 0x01
+#define TAS5760_MUTE_R_MASK 0x02
+#define TAS5760_MUTE_MASK (TAS5760_MUTE_L_MASK | TAS5760_MUTE_R_MASK)
+
+#define TAS5760_DIGITAL_CLIP_MAX_VAL 0xFFFFF
+#define TAS5760_DIGITAL_CLIP_MASK 0xFC
+#define TAS5760_DIGITAL_CLIP1_VAL(val) ((val) << 2)
+#define TAS5760_DIGITAL_CLIP2_VAL(val) ((val) >> 6)
+#define TAS5760_DIGITAL_CLIP3_VAL(val) ((val) >> 12)
+
+#define TAS5760_DIGITAL_BOOST_MASK 0x30
+#define TAS5760_DIGITAL_BOOST_VAL(val) ((val) << 4)
+
+#define TAS5760_ANALOG_GAIN_MASK 0x0C
+#define TAS5760_ANALOG_GAIN_VAL(val) ((val) << 2)
+
+#define TAS5760_PWM_RATE_MAX 7
+#define TAS5760_PWM_RATE_MASK 0x70
+#define TAS5760_PWM_RATE_VAL(val) ((val) << 4)
+
+
+#endif /* _SND_SOC_CODEC_TAS5760_H_ */

--
To view, visit https://chromium-review.googlesource.com/264071
To unsubscribe, visit https://chromium-review.googlesource.com/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I0385bf0dba0f736ddbf47bc27f4171618df04f37
Gerrit-PatchSet: 1
Gerrit-Project: chromiumos/third_party/kernel
Gerrit-Branch: chromeos-3.14
Gerrit-Owner: Sushain Razdan <sushain...@imgtec.com>

Sushain Razdan (Gerrit)

unread,
Apr 6, 2015, 6:13:19 AM4/6/15
to Andrzej Bieniek, Sachin Deodhar, Gaurav Singh, Dylan Rajaratnam
Sushain Razdan has posted comments on this change.

Change subject: Asoc driver and device tree config for TAS5760 codec and
speaker amplifier. Location: sound/soc/codec Initalises and configures the
chip with desired configuration and defines mixer controls as per Alsa's
control architecture. TEST: 1.Verified whether the
......................................................................


Patch Set 1: Verified+1
Gerrit-MessageType: comment
Gerrit-Change-Id: I0385bf0dba0f736ddbf47bc27f4171618df04f37
Gerrit-PatchSet: 1
Gerrit-Project: chromiumos/third_party/kernel
Gerrit-Branch: chromeos-3.14
Gerrit-Owner: Sushain Razdan <sushain...@imgtec.com>
Gerrit-Reviewer: Andrzej Bieniek <andrzej...@pure.com>
Gerrit-Reviewer: Dylan Rajaratnam <dylan.ra...@pure.com>
Gerrit-Reviewer: Gaurav Singh <gaurav...@imgtec.com>
Gerrit-Reviewer: Sachin Deodhar <sachin....@pure.com>
Gerrit-Reviewer: Sushain Razdan <sushain...@imgtec.com>
Gerrit-HasComments: No

Sachin Deodhar (Gerrit)

unread,
Apr 7, 2015, 6:00:32 AM4/7/15
to Sushain Razdan, Andrzej Bieniek, Gaurav Singh, Dylan Rajaratnam
Sachin Deodhar has posted comments on this change.

Change subject: Asoc driver and device tree config for TAS5760 codec and
speaker amplifier. Location: sound/soc/codec Initalises and configures the
chip with desired configuration and defines mixer controls as per Alsa's
control architecture. TEST: 1.Verified whether the
......................................................................


Patch Set 1:

(6 comments)

https://chromium-review.googlesource.com/#/c/264071/1/sound/soc/codecs/tas5760.c
File sound/soc/codecs/tas5760.c:

Line 80: static int tas5760_set_sysclk(struct snd_soc_dai *dai,
: int clk_id, unsigned int freq, int dir)
: {
: struct device *dev = dai->codec->dev;
:
: dev_dbg(dev, "clkid:%d, freq:%d, dir:%d", clk_id, freq, dir);
: return 0;
: }
Looks like it is just a stub. Is it mandatory to provide this function?


Line 100: static int tas5760_hw_params(struct snd_pcm_substream *substream,
: struct snd_pcm_hw_params *params,
: struct snd_soc_dai *dai)
: {
: return 0;
: }
Looks like it is just a stub. Is it mandatory to provide this function?


Line 126: PTR_ERR(hw_config));
If there is no hardware config then we we want to continue with the init of
return with error from here itself?


Line 198: case 6:
Since we are reading the int for a property from the device tree, may be it
would help to explain what these specific numbers signify.


Line 225: case 192:
Since we are reading the int for a property from the device tree, may be it
would help to explain what these specific numbers signify.


Line 428:
Extra empty line.
Gerrit-MessageType: comment
Gerrit-Change-Id: I0385bf0dba0f736ddbf47bc27f4171618df04f37
Gerrit-PatchSet: 1
Gerrit-Project: chromiumos/third_party/kernel
Gerrit-Branch: chromeos-3.14
Gerrit-Owner: Sushain Razdan <sushain...@imgtec.com>
Gerrit-Reviewer: Andrzej Bieniek <andrzej...@pure.com>
Gerrit-Reviewer: Dylan Rajaratnam <dylan.ra...@pure.com>
Gerrit-Reviewer: Gaurav Singh <gaurav...@imgtec.com>
Gerrit-Reviewer: Sachin Deodhar <sachin....@pure.com>
Gerrit-Reviewer: Sushain Razdan <sushain...@imgtec.com>
Gerrit-HasComments: Yes
Reply all
Reply to author
Forward
0 new messages