diff options
| -rw-r--r-- | sound/soc/codecs/cs35l45-tables.c | 4 | ||||
| -rw-r--r-- | sound/soc/codecs/cs35l45.c | 89 | ||||
| -rw-r--r-- | sound/soc/codecs/cs35l45.h | 23 |
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; |
