diff options
| -rw-r--r-- | include/sound/cs35l56.h | 2 | ||||
| -rw-r--r-- | sound/soc/codecs/cs35l56-shared.c | 63 | ||||
| -rw-r--r-- | sound/soc/codecs/cs35l56.c | 24 | 
3 files changed, 67 insertions, 22 deletions
| diff --git a/include/sound/cs35l56.h b/include/sound/cs35l56.h index e0629699b563..1a3c6f66f620 100644 --- a/include/sound/cs35l56.h +++ b/include/sound/cs35l56.h @@ -267,6 +267,7 @@ struct cs35l56_base {  	bool fw_patched;  	bool secured;  	bool can_hibernate; +	bool fw_owns_asp1;  	bool cal_data_valid;  	s8 cal_index;  	struct cirrus_amp_cal_data cal_data; @@ -283,6 +284,7 @@ extern const char * const cs35l56_tx_input_texts[CS35L56_NUM_INPUT_SRC];  extern const unsigned int cs35l56_tx_input_values[CS35L56_NUM_INPUT_SRC];  int cs35l56_set_patch(struct cs35l56_base *cs35l56_base); +int cs35l56_init_asp1_regs_for_driver_control(struct cs35l56_base *cs35l56_base);  int cs35l56_force_sync_asp1_registers_from_cache(struct cs35l56_base *cs35l56_base);  int cs35l56_mbox_send(struct cs35l56_base *cs35l56_base, unsigned int command);  int cs35l56_firmware_shutdown(struct cs35l56_base *cs35l56_base); diff --git a/sound/soc/codecs/cs35l56-shared.c b/sound/soc/codecs/cs35l56-shared.c index a83317db75ed..ec1d95e57061 100644 --- a/sound/soc/codecs/cs35l56-shared.c +++ b/sound/soc/codecs/cs35l56-shared.c @@ -40,16 +40,11 @@ EXPORT_SYMBOL_NS_GPL(cs35l56_set_patch, SND_SOC_CS35L56_SHARED);  static const struct reg_default cs35l56_reg_defaults[] = {  	/* no defaults for OTP_MEM - first read populates cache */ -	{ CS35L56_ASP1_ENABLES1,		0x00000000 }, -	{ CS35L56_ASP1_CONTROL1,		0x00000028 }, -	{ CS35L56_ASP1_CONTROL2,		0x18180200 }, -	{ CS35L56_ASP1_CONTROL3,		0x00000002 }, -	{ CS35L56_ASP1_FRAME_CONTROL1,		0x03020100 }, -	{ CS35L56_ASP1_FRAME_CONTROL5,		0x00020100 }, -	{ CS35L56_ASP1_DATA_CONTROL1,		0x00000018 }, -	{ CS35L56_ASP1_DATA_CONTROL5,		0x00000018 }, - -	/* no defaults for ASP1TX mixer */ +	/* +	 * No defaults for ASP1 control or ASP1TX mixer. See +	 * cs35l56_populate_asp1_register_defaults() and +	 * cs35l56_sync_asp1_mixer_widgets_with_firmware(). +	 */  	{ CS35L56_SWIRE_DP3_CH1_INPUT,		0x00000018 },  	{ CS35L56_SWIRE_DP3_CH2_INPUT,		0x00000019 }, @@ -210,6 +205,36 @@ static bool cs35l56_volatile_reg(struct device *dev, unsigned int reg)  	}  } +static const struct reg_sequence cs35l56_asp1_defaults[] = { +	REG_SEQ0(CS35L56_ASP1_ENABLES1,		0x00000000), +	REG_SEQ0(CS35L56_ASP1_CONTROL1,		0x00000028), +	REG_SEQ0(CS35L56_ASP1_CONTROL2,		0x18180200), +	REG_SEQ0(CS35L56_ASP1_CONTROL3,		0x00000002), +	REG_SEQ0(CS35L56_ASP1_FRAME_CONTROL1,	0x03020100), +	REG_SEQ0(CS35L56_ASP1_FRAME_CONTROL5,	0x00020100), +	REG_SEQ0(CS35L56_ASP1_DATA_CONTROL1,	0x00000018), +	REG_SEQ0(CS35L56_ASP1_DATA_CONTROL5,	0x00000018), +}; + +/* + * The firmware can have control of the ASP so we don't provide regmap + * with defaults for these registers, to prevent a regcache_sync() from + * overwriting the firmware settings. But if the machine driver hooks up + * the ASP it means the driver is taking control of the ASP, so then the + * registers are populated with the defaults. + */ +int cs35l56_init_asp1_regs_for_driver_control(struct cs35l56_base *cs35l56_base) +{ +	if (!cs35l56_base->fw_owns_asp1) +		return 0; + +	cs35l56_base->fw_owns_asp1 = false; + +	return regmap_multi_reg_write(cs35l56_base->regmap, cs35l56_asp1_defaults, +				      ARRAY_SIZE(cs35l56_asp1_defaults)); +} +EXPORT_SYMBOL_NS_GPL(cs35l56_init_asp1_regs_for_driver_control, SND_SOC_CS35L56_SHARED); +  /*   * The firmware boot sequence can overwrite the ASP1 config registers so that   * they don't match regmap's view of their values. Rewrite the values from the @@ -217,19 +242,15 @@ static bool cs35l56_volatile_reg(struct device *dev, unsigned int reg)   */  int cs35l56_force_sync_asp1_registers_from_cache(struct cs35l56_base *cs35l56_base)  { -	struct reg_sequence asp1_regs[] = { -		{ .reg = CS35L56_ASP1_ENABLES1 }, -		{ .reg = CS35L56_ASP1_CONTROL1 }, -		{ .reg = CS35L56_ASP1_CONTROL2 }, -		{ .reg = CS35L56_ASP1_CONTROL3 }, -		{ .reg = CS35L56_ASP1_FRAME_CONTROL1 }, -		{ .reg = CS35L56_ASP1_FRAME_CONTROL5 }, -		{ .reg = CS35L56_ASP1_DATA_CONTROL1 }, -		{ .reg = CS35L56_ASP1_DATA_CONTROL5 }, -	}; +	struct reg_sequence asp1_regs[ARRAY_SIZE(cs35l56_asp1_defaults)];  	int i, ret; -	/* Read values from regmap cache into a write sequence */ +	if (cs35l56_base->fw_owns_asp1) +		return 0; + +	memcpy(asp1_regs, cs35l56_asp1_defaults, sizeof(asp1_regs)); + +	/* Read current values from regmap cache into the write sequence */  	for (i = 0; i < ARRAY_SIZE(asp1_regs); ++i) {  		ret = regmap_read(cs35l56_base->regmap, asp1_regs[i].reg, &asp1_regs[i].def);  		if (ret) diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index 5a4e0e479414..6331b8c6136e 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -454,9 +454,14 @@ static int cs35l56_asp_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int f  {  	struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(codec_dai->component);  	unsigned int val; +	int ret;  	dev_dbg(cs35l56->base.dev, "%s: %#x\n", __func__, fmt); +	ret = cs35l56_init_asp1_regs_for_driver_control(&cs35l56->base); +	if (ret) +		return ret; +  	switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {  	case SND_SOC_DAIFMT_CBC_CFC:  		break; @@ -530,6 +535,11 @@ static int cs35l56_asp_dai_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx  					unsigned int rx_mask, int slots, int slot_width)  {  	struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component); +	int ret; + +	ret = cs35l56_init_asp1_regs_for_driver_control(&cs35l56->base); +	if (ret) +		return ret;  	if ((slots == 0) || (slot_width == 0)) {  		dev_dbg(cs35l56->base.dev, "tdm config cleared\n"); @@ -578,6 +588,11 @@ static int cs35l56_asp_dai_hw_params(struct snd_pcm_substream *substream,  	struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component);  	unsigned int rate = params_rate(params);  	u8 asp_width, asp_wl; +	int ret; + +	ret = cs35l56_init_asp1_regs_for_driver_control(&cs35l56->base); +	if (ret) +		return ret;  	asp_wl = params_width(params);  	if (cs35l56->asp_slot_width) @@ -634,7 +649,11 @@ static int cs35l56_asp_dai_set_sysclk(struct snd_soc_dai *dai,  				      int clk_id, unsigned int freq, int dir)  {  	struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component); -	int freq_id; +	int freq_id, ret; + +	ret = cs35l56_init_asp1_regs_for_driver_control(&cs35l56->base); +	if (ret) +		return ret;  	if (freq == 0) {  		cs35l56->sysclk_set = false; @@ -1403,6 +1422,9 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56)  	cs35l56->base.cal_index = -1;  	cs35l56->speaker_id = -ENOENT; +	/* Assume that the firmware owns ASP1 until we know different */ +	cs35l56->base.fw_owns_asp1 = true; +  	dev_set_drvdata(cs35l56->base.dev, cs35l56);  	cs35l56_fill_supply_names(cs35l56->supplies); | 
