Unverified Commit 7c15e4ca authored by Mark Brown's avatar Mark Brown
Browse files

ASoC: cs35l56: Fixes for CS35L63 for production

Merge series from Stefan Binding <sbinding@opensource.cirrus.com>:

Production silicon for CS36L63 has some small differences compared to
pre-production silicon. This requires small fixes in driver.
Update firmware addresses, tuning algorithm IDs and remove soundwire
clock workaround as no longer necessary.

No product was ever released using pre-production silicon, therefore
there is no need to keep support for it.
parents af24c20c 8d13d1bd
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -107,8 +107,8 @@
#define CS35L56_DSP1_PMEM_5114				0x3804FE8

#define CS35L63_DSP1_FW_VER				CS35L56_DSP1_FW_VER
#define CS35L63_DSP1_HALO_STATE				0x280396C
#define CS35L63_DSP1_PM_CUR_STATE			0x28042C8
#define CS35L63_DSP1_HALO_STATE				0x2803C04
#define CS35L63_DSP1_PM_CUR_STATE			0x2804518
#define CS35L63_PROTECTION_STATUS			0x340009C
#define CS35L63_TRANSDUCER_ACTUAL_PS			0x34000F4
#define CS35L63_MAIN_RENDER_USER_MUTE			0x3400020
@@ -306,6 +306,7 @@ struct cs35l56_base {
	struct gpio_desc *reset_gpio;
	struct cs35l56_spi_payload *spi_payload_buf;
	const struct cs35l56_fw_reg *fw_reg;
	const struct cirrus_amp_cal_controls *calibration_controls;
};

static inline bool cs35l56_is_otp_register(unsigned int reg)
+0 −69
Original line number Diff line number Diff line
@@ -393,74 +393,6 @@ static int cs35l56_sdw_update_status(struct sdw_slave *peripheral,
	return 0;
}

static int cs35l63_sdw_kick_divider(struct cs35l56_private *cs35l56,
				    struct sdw_slave *peripheral)
{
	unsigned int curr_scale_reg, next_scale_reg;
	int curr_scale, next_scale, ret;

	if (!cs35l56->base.init_done)
		return 0;

	if (peripheral->bus->params.curr_bank) {
		curr_scale_reg = SDW_SCP_BUSCLOCK_SCALE_B1;
		next_scale_reg = SDW_SCP_BUSCLOCK_SCALE_B0;
	} else {
		curr_scale_reg = SDW_SCP_BUSCLOCK_SCALE_B0;
		next_scale_reg = SDW_SCP_BUSCLOCK_SCALE_B1;
	}

	/*
	 * Current clock scale value must be different to new value.
	 * Modify current to guarantee this. If next still has the dummy
	 * value we wrote when it was current, the core code has not set
	 * a new scale so restore its original good value
	 */
	curr_scale = sdw_read_no_pm(peripheral, curr_scale_reg);
	if (curr_scale < 0) {
		dev_err(cs35l56->base.dev, "Failed to read current clock scale: %d\n", curr_scale);
		return curr_scale;
	}

	next_scale = sdw_read_no_pm(peripheral, next_scale_reg);
	if (next_scale < 0) {
		dev_err(cs35l56->base.dev, "Failed to read next clock scale: %d\n", next_scale);
		return next_scale;
	}

	if (next_scale == CS35L56_SDW_INVALID_BUS_SCALE) {
		next_scale = cs35l56->old_sdw_clock_scale;
		ret = sdw_write_no_pm(peripheral, next_scale_reg, next_scale);
		if (ret < 0) {
			dev_err(cs35l56->base.dev, "Failed to modify current clock scale: %d\n",
				ret);
			return ret;
		}
	}

	cs35l56->old_sdw_clock_scale = curr_scale;
	ret = sdw_write_no_pm(peripheral, curr_scale_reg, CS35L56_SDW_INVALID_BUS_SCALE);
	if (ret < 0) {
		dev_err(cs35l56->base.dev, "Failed to modify current clock scale: %d\n", ret);
		return ret;
	}

	dev_dbg(cs35l56->base.dev, "Next bus scale: %#x\n", next_scale);

	return 0;
}

static int cs35l56_sdw_bus_config(struct sdw_slave *peripheral,
				  struct sdw_bus_params *params)
{
	struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev);

	if ((cs35l56->base.type == 0x63) && (cs35l56->base.rev < 0xa1))
		return cs35l63_sdw_kick_divider(cs35l56, peripheral);

	return 0;
}

static int __maybe_unused cs35l56_sdw_clk_stop(struct sdw_slave *peripheral,
					       enum sdw_clk_stop_mode mode,
					       enum sdw_clk_stop_type type)
@@ -476,7 +408,6 @@ static const struct sdw_slave_ops cs35l56_sdw_ops = {
	.read_prop = cs35l56_sdw_read_prop,
	.interrupt_callback = cs35l56_sdw_interrupt,
	.update_status = cs35l56_sdw_update_status,
	.bus_config = cs35l56_sdw_bus_config,
#ifdef DEBUG
	.clk_stop = cs35l56_sdw_clk_stop,
#endif
+26 −3
Original line number Diff line number Diff line
@@ -838,6 +838,15 @@ const struct cirrus_amp_cal_controls cs35l56_calibration_controls = {
};
EXPORT_SYMBOL_NS_GPL(cs35l56_calibration_controls, "SND_SOC_CS35L56_SHARED");

static const struct cirrus_amp_cal_controls cs35l63_calibration_controls = {
	.alg_id =	0xbf210,
	.mem_region =	WMFW_ADSP2_YM,
	.ambient =	"CAL_AMBIENT",
	.calr =		"CAL_R",
	.status =	"CAL_STATUS",
	.checksum =	"CAL_CHECKSUM",
};

int cs35l56_get_calibration(struct cs35l56_base *cs35l56_base)
{
	u64 silicon_uid = 0;
@@ -912,19 +921,31 @@ EXPORT_SYMBOL_NS_GPL(cs35l56_read_prot_status, "SND_SOC_CS35L56_SHARED");
void cs35l56_log_tuning(struct cs35l56_base *cs35l56_base, struct cs_dsp *cs_dsp)
{
	__be32 pid, sid, tid;
	unsigned int alg_id;
	int ret;

	switch (cs35l56_base->type) {
	case 0x54:
	case 0x56:
	case 0x57:
		alg_id = 0x9f212;
		break;
	default:
		alg_id = 0xbf212;
		break;
	}

	scoped_guard(mutex, &cs_dsp->pwr_lock) {
		ret = cs_dsp_coeff_read_ctrl(cs_dsp_get_ctl(cs_dsp, "AS_PRJCT_ID",
							    WMFW_ADSP2_XM, 0x9f212),
							    WMFW_ADSP2_XM, alg_id),
					     0, &pid, sizeof(pid));
		if (!ret)
			ret = cs_dsp_coeff_read_ctrl(cs_dsp_get_ctl(cs_dsp, "AS_CHNNL_ID",
								    WMFW_ADSP2_XM, 0x9f212),
								    WMFW_ADSP2_XM, alg_id),
						     0, &sid, sizeof(sid));
		if (!ret)
			ret = cs_dsp_coeff_read_ctrl(cs_dsp_get_ctl(cs_dsp, "AS_SNPSHT_ID",
								    WMFW_ADSP2_XM, 0x9f212),
								    WMFW_ADSP2_XM, alg_id),
						     0, &tid, sizeof(tid));
	}

@@ -974,8 +995,10 @@ int cs35l56_hw_init(struct cs35l56_base *cs35l56_base)
	case 0x35A54:
	case 0x35A56:
	case 0x35A57:
		cs35l56_base->calibration_controls = &cs35l56_calibration_controls;
		break;
	case 0x35A630:
		cs35l56_base->calibration_controls = &cs35l63_calibration_controls;
		devid = devid >> 4;
		break;
	default:
+1 −1
Original line number Diff line number Diff line
@@ -695,7 +695,7 @@ static int cs35l56_write_cal(struct cs35l56_private *cs35l56)
		return ret;

	ret = cs_amp_write_cal_coeffs(&cs35l56->dsp.cs_dsp,
				      &cs35l56_calibration_controls,
				      cs35l56->base.calibration_controls,
				      &cs35l56->base.cal_data);

	wm_adsp_stop(&cs35l56->dsp);
+0 −3
Original line number Diff line number Diff line
@@ -20,8 +20,6 @@
#define CS35L56_SDW_GEN_INT_MASK_1	0xc1
#define CS35L56_SDW_INT_MASK_CODEC_IRQ	BIT(0)

#define CS35L56_SDW_INVALID_BUS_SCALE	0xf

#define CS35L56_RX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
#define CS35L56_TX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE \
			    | SNDRV_PCM_FMTBIT_S32_LE)
@@ -52,7 +50,6 @@ struct cs35l56_private {
	u8 asp_slot_count;
	bool tdm_mode;
	bool sysclk_set;
	u8 old_sdw_clock_scale;
	u8 sdw_link_num;
	u8 sdw_unique_id;
};