summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2025-08-20 19:56:20 +0100
committerMark Brown <broonie@kernel.org>2025-08-20 19:56:20 +0100
commit7c15e4cabfa96ed3cd717a2ed7a9961268ab21f7 (patch)
tree4344d98dd3567a4229662c8a957f53a90018c1f9
parentaf24c20c4633a667ac5b5e20cf9d96f6176a0ca3 (diff)
parent8d13d1bdb59d0a2c526869ee571ec51a3a887463 (diff)
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.
-rw-r--r--include/sound/cs35l56.h5
-rw-r--r--sound/soc/codecs/cs35l56-sdw.c69
-rw-r--r--sound/soc/codecs/cs35l56-shared.c29
-rw-r--r--sound/soc/codecs/cs35l56.c2
-rw-r--r--sound/soc/codecs/cs35l56.h3
5 files changed, 30 insertions, 78 deletions
diff --git a/include/sound/cs35l56.h b/include/sound/cs35l56.h
index e17c4cadd04d..7c8bbe8ad1e2 100644
--- a/include/sound/cs35l56.h
+++ b/include/sound/cs35l56.h
@@ -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)
diff --git a/sound/soc/codecs/cs35l56-sdw.c b/sound/soc/codecs/cs35l56-sdw.c
index ee14031695a1..3905c9cb188a 100644
--- a/sound/soc/codecs/cs35l56-sdw.c
+++ b/sound/soc/codecs/cs35l56-sdw.c
@@ -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
diff --git a/sound/soc/codecs/cs35l56-shared.c b/sound/soc/codecs/cs35l56-shared.c
index ba653f6ccfae..850fcf385996 100644
--- a/sound/soc/codecs/cs35l56-shared.c
+++ b/sound/soc/codecs/cs35l56-shared.c
@@ -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:
diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c
index b1c65d8331e7..2c1edbd636ef 100644
--- a/sound/soc/codecs/cs35l56.c
+++ b/sound/soc/codecs/cs35l56.c
@@ -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);
diff --git a/sound/soc/codecs/cs35l56.h b/sound/soc/codecs/cs35l56.h
index bd77a57249d7..40a1800a4585 100644
--- a/sound/soc/codecs/cs35l56.h
+++ b/sound/soc/codecs/cs35l56.h
@@ -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;
};