summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sound/soc/codecs/cs35l45-tables.c4
-rw-r--r--sound/soc/codecs/cs35l45.c89
-rw-r--r--sound/soc/codecs/cs35l45.h23
3 files changed, 112 insertions, 4 deletions
diff --git a/sound/soc/codecs/cs35l45-tables.c b/sound/soc/codecs/cs35l45-tables.c
index 764dbaa35042..57982b8ae645 100644
--- a/sound/soc/codecs/cs35l45-tables.c
+++ b/sound/soc/codecs/cs35l45-tables.c
@@ -51,6 +51,8 @@ static const struct reg_default cs35l45_defaults[] = {
{ CS35L45_WKI2C_CTL, 0x00000030 },
{ CS35L45_REFCLK_INPUT, 0x00000510 },
{ CS35L45_GLOBAL_SAMPLE_RATE, 0x00000003 },
+ { CS35L45_SYNC_TX_RX_ENABLES, 0x00000200 },
+ { CS35L45_SYNC_SW_TX_ID, 0x00000000 },
{ CS35L45_ASP_ENABLES1, 0x00000000 },
{ CS35L45_ASP_CONTROL1, 0x00000028 },
{ CS35L45_ASP_CONTROL2, 0x18180200 },
@@ -134,6 +136,8 @@ static bool cs35l45_readable_reg(struct device *dev, unsigned int reg)
case CS35L45_PWRMGT_STS:
case CS35L45_REFCLK_INPUT:
case CS35L45_GLOBAL_SAMPLE_RATE:
+ case CS35L45_SYNC_TX_RX_ENABLES:
+ case CS35L45_SYNC_SW_TX_ID:
case CS35L45_ASP_ENABLES1:
case CS35L45_ASP_CONTROL1:
case CS35L45_ASP_CONTROL2:
diff --git a/sound/soc/codecs/cs35l45.c b/sound/soc/codecs/cs35l45.c
index a032bb23b4ac..763cd83b5d6d 100644
--- a/sound/soc/codecs/cs35l45.c
+++ b/sound/soc/codecs/cs35l45.c
@@ -6,6 +6,7 @@
//
// Author: James Schulman <james.schulman@cirrus.com>
+#include <linux/bitfield.h>
#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
@@ -195,6 +196,46 @@ static int cs35l45_activate_ctl(struct snd_soc_component *component,
return 0;
}
+static int cs35l45_sync_en_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+ struct cs35l45_private *cs35l45 =
+ snd_soc_component_get_drvdata(component);
+
+ ucontrol->value.integer.value[0] = cs35l45->sync_en;
+
+ return 0;
+}
+
+static int cs35l45_sync_en_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+ struct cs35l45_private *cs35l45 =
+ snd_soc_component_get_drvdata(component);
+ struct snd_soc_dapm_context *dapm =
+ snd_soc_component_to_dapm(component);
+
+ snd_soc_dapm_mutex_lock(dapm);
+
+ if ((bool)ucontrol->value.integer.value[0] == cs35l45->sync_en) {
+ snd_soc_dapm_mutex_unlock(dapm);
+ return 0;
+ }
+
+ if ((bool)ucontrol->value.integer.value[0])
+ regmap_set_bits(cs35l45->regmap, CS35L45_BLOCK_ENABLES2, CS35L45_SYNC_EN_MASK);
+ else
+ regmap_clear_bits(cs35l45->regmap, CS35L45_BLOCK_ENABLES2, CS35L45_SYNC_EN_MASK);
+
+ cs35l45->sync_en = (bool)ucontrol->value.integer.value[0];
+
+ snd_soc_dapm_mutex_unlock(dapm);
+
+ return 1;
+}
+
static int cs35l45_amplifier_mode_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -591,6 +632,18 @@ static SOC_ENUM_SINGLE_DECL(amplifier_mode_enum, SND_SOC_NOPM, 0,
static DECLARE_TLV_DB_SCALE(amp_gain_tlv, 1000, 300, 0);
static const DECLARE_TLV_DB_SCALE(cs35l45_dig_pcm_vol_tlv, -10225, 25, true);
+static const struct snd_kcontrol_new cs35l45_sync_controls[] = {
+ SOC_SINGLE_BOOL_EXT("SYNC Switch", 0, cs35l45_sync_en_get, cs35l45_sync_en_put),
+ SOC_SINGLE("SYNC LSW RX Switch", CS35L45_SYNC_TX_RX_ENABLES,
+ CS35L45_SYNC_LSW_RX_EN_SHIFT, 1, 0),
+ SOC_SINGLE("SYNC LSW TX Switch", CS35L45_SYNC_TX_RX_ENABLES,
+ CS35L45_SYNC_LSW_TX_EN_SHIFT, 1, 0),
+ SOC_SINGLE("SYNC SW RX Switch", CS35L45_SYNC_TX_RX_ENABLES,
+ CS35L45_SYNC_SW_RX_EN_SHIFT, 1, 0),
+ SOC_SINGLE("SYNC SW TX Switch", CS35L45_SYNC_TX_RX_ENABLES,
+ CS35L45_SYNC_SW_TX_EN_SHIFT, 1, 0),
+};
+
static const struct snd_kcontrol_new cs35l45_controls[] = {
SOC_ENUM_EXT("Amplifier Mode", amplifier_mode_enum,
cs35l45_amplifier_mode_get, cs35l45_amplifier_mode_put),
@@ -880,6 +933,19 @@ static struct snd_soc_dai_driver cs35l45_dai[] = {
static int cs35l45_component_probe(struct snd_soc_component *component)
{
struct cs35l45_private *cs35l45 = snd_soc_component_get_drvdata(component);
+ int ret;
+
+ ret = snd_soc_add_component_controls(component, cs35l45_controls,
+ ARRAY_SIZE(cs35l45_controls));
+ if (ret < 0)
+ return ret;
+
+ if (cs35l45->sync_pin_set) {
+ ret = snd_soc_add_component_controls(component, cs35l45_sync_controls,
+ ARRAY_SIZE(cs35l45_sync_controls));
+ if (ret < 0)
+ return ret;
+ }
return wm_adsp2_component_probe(&cs35l45->dsp, component);
}
@@ -901,9 +967,6 @@ static const struct snd_soc_component_driver cs35l45_component = {
.dapm_routes = cs35l45_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(cs35l45_dapm_routes),
- .controls = cs35l45_controls,
- .num_controls = ARRAY_SIZE(cs35l45_controls),
-
.name = "cs35l45",
.endianness = 1,
@@ -1064,6 +1127,19 @@ static int cs35l45_sys_resume(struct device *dev)
return 0;
}
+static void cs35l45_apply_sync_property_config(struct cs35l45_private *cs35l45)
+{
+ unsigned int val;
+
+ if (device_property_read_u32(cs35l45->dev, "cirrus,sync-lsw-txid", &val) == 0)
+ regmap_update_bits(cs35l45->regmap, CS35L45_SYNC_SW_TX_ID,
+ CS35L45_SYNC_LSW_TXID_MASK, val << CS35L45_SYNC_LSW_TXID_SHIFT);
+
+ if (device_property_read_u32(cs35l45->dev, "cirrus,sync-sw-txid", &val) == 0)
+ regmap_update_bits(cs35l45->regmap, CS35L45_SYNC_SW_TX_ID,
+ CS35L45_SYNC_SW_TXID_MASK, val);
+}
+
static int cs35l45_apply_property_config(struct cs35l45_private *cs35l45)
{
struct device_node *node = cs35l45->dev->of_node;
@@ -1110,10 +1186,15 @@ static int cs35l45_apply_property_config(struct cs35l45_private *cs35l45)
val << CS35L45_GPIO_POL_SHIFT);
ret = of_property_read_u32(child, "gpio-ctrl", &val);
- if (!ret)
+ if (!ret) {
+ if ((i == 0) && (val == CS35L45_GP1_CTRL_MDSYNC)) {
+ cs35l45->sync_pin_set = true;
+ cs35l45_apply_sync_property_config(cs35l45);
+ }
regmap_update_bits(cs35l45->regmap, pad_regs[i],
CS35L45_GPIO_CTRL_MASK,
val << CS35L45_GPIO_CTRL_SHIFT);
+ }
ret = of_property_read_u32(child, "gpio-invert", &val);
if (!ret) {
diff --git a/sound/soc/codecs/cs35l45.h b/sound/soc/codecs/cs35l45.h
index 7a790d2acac7..f8a4713ae92f 100644
--- a/sound/soc/codecs/cs35l45.h
+++ b/sound/soc/codecs/cs35l45.h
@@ -35,6 +35,8 @@
#define CS35L45_PWRMGT_STS 0x0000290C
#define CS35L45_REFCLK_INPUT 0x00002C04
#define CS35L45_GLOBAL_SAMPLE_RATE 0x00002C0C
+#define CS35L45_SYNC_TX_RX_ENABLES 0x00003400
+#define CS35L45_SYNC_SW_TX_ID 0x00003408
#define CS35L45_BOOST_CCM_CFG 0x00003808
#define CS35L45_BOOST_DCM_CFG 0x0000380C
#define CS35L45_BOOST_OV_CFG 0x0000382C
@@ -183,6 +185,8 @@
#define CS35L45_ASP_EN_SHIFT 27
#define CS35L45_AMP_DRE_EN_SHIFT 20
#define CS35L45_AMP_DRE_EN_MASK BIT(20)
+#define CS35L45_SYNC_EN_SHIFT 8
+#define CS35L45_SYNC_EN_MASK BIT(8)
#define CS35L45_MEM_RDY_SHIFT 1
#define CS35L45_MEM_RDY_MASK BIT(1)
@@ -220,6 +224,22 @@
#define CS35L45_44P100_KHZ 0x0B
#define CS35L45_88P200_KHZ 0x0C
+/* SYNC_TX_RX_ENABLES */
+#define CS35L45_SYNC_LSW_RX_EN_SHIFT 19
+#define CS35L45_SYNC_LSW_RX_EN_MASK BIT(19)
+#define CS35L45_SYNC_LSW_TX_EN_SHIFT 18
+#define CS35L45_SYNC_LSW_TX_EN_MASK BIT(18)
+#define CS35L45_SYNC_SW_RX_EN_SHIFT 17
+#define CS35L45_SYNC_SW_RX_EN_MASK BIT(17)
+#define CS35L45_SYNC_SW_TX_EN_SHIFT 16
+#define CS35L45_SYNC_SW_TX_EN_MASK BIT(16)
+
+/* SYNC_SW_TX_ID */
+#define CS35L45_SYNC_LSW_TXID_SHIFT 8
+#define CS35L45_SYNC_LSW_TXID_MASK GENMASK(10, 8)
+#define CS35L45_SYNC_SW_TXID_SHIFT 0
+#define CS35L45_SYNC_SW_TXID_MASK GENMASK(2, 0)
+
/* ASP_ENABLES_1 */
#define CS35L45_ASP_RX2_EN_SHIFT 17
#define CS35L45_ASP_RX1_EN_SHIFT 16
@@ -320,6 +340,7 @@
#define CS35L45_GPIO_CTRL_MASK GENMASK(22, 20)
#define CS35L45_GPIO_INVERT_SHIFT 19
#define CS35L45_GPIO_INVERT_MASK BIT(19)
+#define CS35L45_GP1_CTRL_MDSYNC 0x2
/* CS35L45_IRQ1_EINT_1 */
#define CS35L45_BST_UVP_ERR_SHIFT 7
@@ -493,6 +514,8 @@ struct cs35l45_private {
struct regulator *vdd_a;
bool initialized;
bool sysclk_set;
+ bool sync_en;
+ bool sync_pin_set;
u8 slot_width;
u8 slot_count;
int amplifier_mode;