summaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/cs35l56-shared.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/cs35l56-shared.c')
-rw-r--r--sound/soc/codecs/cs35l56-shared.c155
1 files changed, 44 insertions, 111 deletions
diff --git a/sound/soc/codecs/cs35l56-shared.c b/sound/soc/codecs/cs35l56-shared.c
index 8af89a263594..e45e9ae01bc6 100644
--- a/sound/soc/codecs/cs35l56-shared.c
+++ b/sound/soc/codecs/cs35l56-shared.c
@@ -20,10 +20,23 @@ static const struct reg_sequence cs35l56_patch[] = {
* Firmware can change these to non-defaults to satisfy SDCA.
* Ensure that they are at known defaults.
*/
+ { 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 },
+ { CS35L56_ASP1TX1_INPUT, 0x00000000 },
+ { CS35L56_ASP1TX2_INPUT, 0x00000000 },
+ { CS35L56_ASP1TX3_INPUT, 0x00000000 },
+ { CS35L56_ASP1TX4_INPUT, 0x00000000 },
{ CS35L56_SWIRE_DP3_CH1_INPUT, 0x00000018 },
{ CS35L56_SWIRE_DP3_CH2_INPUT, 0x00000019 },
{ CS35L56_SWIRE_DP3_CH3_INPUT, 0x00000029 },
{ CS35L56_SWIRE_DP3_CH4_INPUT, 0x00000028 },
+ { CS35L56_IRQ1_MASK_18, 0x1f7df0ff },
/* These are not reset by a soft-reset, so patch to defaults. */
{ CS35L56_MAIN_RENDER_USER_MUTE, 0x00000000 },
@@ -41,12 +54,18 @@ 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 */
- /*
- * No defaults for ASP1 control or ASP1TX mixer. See
- * cs35l56_populate_asp1_register_defaults() and
- * cs35l56_sync_asp1_mixer_widgets_with_firmware().
- */
-
+ { 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 },
+ { CS35L56_ASP1TX1_INPUT, 0x00000000 },
+ { CS35L56_ASP1TX2_INPUT, 0x00000000 },
+ { CS35L56_ASP1TX3_INPUT, 0x00000000 },
+ { CS35L56_ASP1TX4_INPUT, 0x00000000 },
{ CS35L56_SWIRE_DP3_CH1_INPUT, 0x00000018 },
{ CS35L56_SWIRE_DP3_CH2_INPUT, 0x00000019 },
{ CS35L56_SWIRE_DP3_CH3_INPUT, 0x00000029 },
@@ -206,73 +225,6 @@ 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
- * regmap cache into the hardware registers.
- */
-int cs35l56_force_sync_asp1_registers_from_cache(struct cs35l56_base *cs35l56_base)
-{
- struct reg_sequence asp1_regs[ARRAY_SIZE(cs35l56_asp1_defaults)];
- int i, ret;
-
- 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)
- goto err;
- }
-
- /* Write the values cache-bypassed so that they will be written to silicon */
- ret = regmap_multi_reg_write_bypassed(cs35l56_base->regmap, asp1_regs,
- ARRAY_SIZE(asp1_regs));
- if (ret)
- goto err;
-
- return 0;
-
-err:
- dev_err(cs35l56_base->dev, "Failed to sync ASP1 registers: %d\n", ret);
-
- return ret;
-}
-EXPORT_SYMBOL_NS_GPL(cs35l56_force_sync_asp1_registers_from_cache, SND_SOC_CS35L56_SHARED);
-
int cs35l56_mbox_send(struct cs35l56_base *cs35l56_base, unsigned int command)
{
unsigned int val;
@@ -294,19 +246,13 @@ EXPORT_SYMBOL_NS_GPL(cs35l56_mbox_send, SND_SOC_CS35L56_SHARED);
int cs35l56_firmware_shutdown(struct cs35l56_base *cs35l56_base)
{
int ret;
- unsigned int reg;
unsigned int val;
ret = cs35l56_mbox_send(cs35l56_base, CS35L56_MBOX_CMD_SHUTDOWN);
if (ret)
return ret;
- if (cs35l56_base->rev < CS35L56_REVID_B0)
- reg = CS35L56_DSP1_PM_CUR_STATE_A1;
- else
- reg = CS35L56_DSP1_PM_CUR_STATE;
-
- ret = regmap_read_poll_timeout(cs35l56_base->regmap, reg,
+ ret = regmap_read_poll_timeout(cs35l56_base->regmap, CS35L56_DSP1_PM_CUR_STATE,
val, (val == CS35L56_HALO_STATE_SHUTDOWN),
CS35L56_HALO_STATE_POLL_US,
CS35L56_HALO_STATE_TIMEOUT_US);
@@ -319,15 +265,9 @@ EXPORT_SYMBOL_NS_GPL(cs35l56_firmware_shutdown, SND_SOC_CS35L56_SHARED);
int cs35l56_wait_for_firmware_boot(struct cs35l56_base *cs35l56_base)
{
- unsigned int reg;
unsigned int val = 0;
int read_ret, poll_ret;
- if (cs35l56_base->rev < CS35L56_REVID_B0)
- reg = CS35L56_DSP1_HALO_STATE_A1;
- else
- reg = CS35L56_DSP1_HALO_STATE;
-
/*
* The regmap must remain in cache-only until the chip has
* booted, so use a bypassed read of the status register.
@@ -337,7 +277,7 @@ int cs35l56_wait_for_firmware_boot(struct cs35l56_base *cs35l56_base)
CS35L56_HALO_STATE_POLL_US,
CS35L56_HALO_STATE_TIMEOUT_US,
false,
- cs35l56_base->regmap, reg, &val);
+ cs35l56_base->regmap, CS35L56_DSP1_HALO_STATE, &val);
if (poll_ret) {
dev_err(cs35l56_base->dev, "Firmware boot timed out(%d): HALO_STATE=%#x\n",
@@ -393,7 +333,7 @@ int cs35l56_irq_request(struct cs35l56_base *cs35l56_base, int irq)
{
int ret;
- if (!irq)
+ if (irq < 1)
return 0;
ret = devm_request_threaded_irq(cs35l56_base->dev, irq, NULL, cs35l56_irq,
@@ -511,32 +451,23 @@ static const struct reg_sequence cs35l56_hibernate_seq[] = {
REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_ALLOW_AUTO_HIBERNATE),
};
-static const struct reg_sequence cs35l56_hibernate_wake_seq[] = {
- REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_WAKEUP),
-};
-
static void cs35l56_issue_wake_event(struct cs35l56_base *cs35l56_base)
{
+ unsigned int val;
+
/*
* Dummy transactions to trigger I2C/SPI auto-wake. Issue two
* transactions to meet the minimum required time from the rising edge
* to the last falling edge of wake.
*
- * It uses bypassed write because we must wake the chip before
+ * It uses bypassed read because we must wake the chip before
* disabling regmap cache-only.
- *
- * This can NAK on I2C which will terminate the write sequence so the
- * single-write sequence is issued twice.
*/
- regmap_multi_reg_write_bypassed(cs35l56_base->regmap,
- cs35l56_hibernate_wake_seq,
- ARRAY_SIZE(cs35l56_hibernate_wake_seq));
+ regmap_read_bypassed(cs35l56_base->regmap, CS35L56_IRQ1_STATUS, &val);
usleep_range(CS35L56_WAKE_HOLD_TIME_US, 2 * CS35L56_WAKE_HOLD_TIME_US);
- regmap_multi_reg_write_bypassed(cs35l56_base->regmap,
- cs35l56_hibernate_wake_seq,
- ARRAY_SIZE(cs35l56_hibernate_wake_seq));
+ regmap_read_bypassed(cs35l56_base->regmap, CS35L56_IRQ1_STATUS, &val);
cs35l56_wait_control_port_ready();
}
@@ -775,11 +706,6 @@ int cs35l56_hw_init(struct cs35l56_base *cs35l56_base)
else
cs35l56_wait_control_port_ready();
- /*
- * The HALO_STATE register is in different locations on Ax and B0
- * devices so the REVID needs to be determined before waiting for the
- * firmware to boot.
- */
ret = regmap_read_bypassed(cs35l56_base->regmap, CS35L56_REVID, &revid);
if (ret < 0) {
dev_err(cs35l56_base->dev, "Get Revision ID failed\n");
@@ -853,9 +779,16 @@ EXPORT_SYMBOL_NS_GPL(cs35l56_hw_init, SND_SOC_CS35L56_SHARED);
int cs35l56_get_speaker_id(struct cs35l56_base *cs35l56_base)
{
struct gpio_descs *descs;
- int speaker_id;
+ u32 speaker_id;
int i, ret;
+ /* Attempt to read the speaker type from a device property first */
+ ret = device_property_read_u32(cs35l56_base->dev, "cirrus,speaker-id", &speaker_id);
+ if (!ret) {
+ dev_dbg(cs35l56_base->dev, "Speaker ID = %d\n", speaker_id);
+ return speaker_id;
+ }
+
/* Read the speaker type qualifier from the motherboard GPIOs */
descs = gpiod_get_array_optional(cs35l56_base->dev, "spk-id", GPIOD_IN);
if (!descs) {
@@ -983,7 +916,7 @@ const unsigned int cs35l56_tx_input_values[] = {
};
EXPORT_SYMBOL_NS_GPL(cs35l56_tx_input_values, SND_SOC_CS35L56_SHARED);
-struct regmap_config cs35l56_regmap_i2c = {
+const struct regmap_config cs35l56_regmap_i2c = {
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
@@ -999,7 +932,7 @@ struct regmap_config cs35l56_regmap_i2c = {
};
EXPORT_SYMBOL_NS_GPL(cs35l56_regmap_i2c, SND_SOC_CS35L56_SHARED);
-struct regmap_config cs35l56_regmap_spi = {
+const struct regmap_config cs35l56_regmap_spi = {
.reg_bits = 32,
.val_bits = 32,
.pad_bits = 16,
@@ -1016,7 +949,7 @@ struct regmap_config cs35l56_regmap_spi = {
};
EXPORT_SYMBOL_NS_GPL(cs35l56_regmap_spi, SND_SOC_CS35L56_SHARED);
-struct regmap_config cs35l56_regmap_sdw = {
+const struct regmap_config cs35l56_regmap_sdw = {
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,