staticconststruct reg_sequence cs35l56_patch_fw[] = { /* These are not reset by a soft-reset, so patch to defaults. */
{ CS35L56_MAIN_RENDER_USER_MUTE, 0x00000000 },
{ CS35L56_MAIN_RENDER_USER_VOLUME, 0x00000000 },
{ CS35L56_MAIN_POSTURE_NUMBER, 0x00000000 },
};
staticconststruct reg_sequence cs35l63_patch_fw[] = { /* These are not reset by a soft-reset, so patch to defaults. */
{ CS35L63_MAIN_RENDER_USER_MUTE, 0x00000000 },
{ CS35L63_MAIN_RENDER_USER_VOLUME, 0x00000000 },
{ CS35L63_MAIN_POSTURE_NUMBER, 0x00000000 },
};
int cs35l56_set_patch(struct cs35l56_base *cs35l56_base)
{ int ret;
ret = regmap_register_patch(cs35l56_base->regmap, cs35l56_patch,
ARRAY_SIZE(cs35l56_patch)); if (ret) return ret;
staticbool cs35l56_is_dsp_memory(unsignedint reg)
{ switch (reg) { case CS35L56_DSP1_XMEM_PACKED_0 ... CS35L56_DSP1_XMEM_PACKED_6143: case CS35L56_DSP1_XMEM_UNPACKED32_0 ... CS35L56_DSP1_XMEM_UNPACKED32_4095: case CS35L56_DSP1_XMEM_UNPACKED24_0 ... CS35L56_DSP1_XMEM_UNPACKED24_8191: case CS35L56_DSP1_YMEM_PACKED_0 ... CS35L56_DSP1_YMEM_PACKED_4604: case CS35L56_DSP1_YMEM_UNPACKED32_0 ... CS35L56_DSP1_YMEM_UNPACKED32_3070: case CS35L56_DSP1_YMEM_UNPACKED24_0 ... CS35L56_DSP1_YMEM_UNPACKED24_6141: case CS35L56_DSP1_PMEM_0 ... CS35L56_DSP1_PMEM_5114: returntrue; default: returnfalse;
}
}
staticbool cs35l56_readable_reg(struct device *dev, unsignedint reg)
{ switch (reg) { case CS35L56_DEVID: case CS35L56_REVID: case CS35L56_RELID: case CS35L56_OTPID: case CS35L56_SFT_RESET: case CS35L56_GLOBAL_ENABLES: case CS35L56_BLOCK_ENABLES: case CS35L56_BLOCK_ENABLES2: case CS35L56_REFCLK_INPUT: case CS35L56_GLOBAL_SAMPLE_RATE: case CS35L56_OTP_MEM_53: case CS35L56_OTP_MEM_54: case CS35L56_OTP_MEM_55: case CS35L56_ASP1_ENABLES1: case CS35L56_ASP1_CONTROL1: case CS35L56_ASP1_CONTROL2: case CS35L56_ASP1_CONTROL3: case CS35L56_ASP1_FRAME_CONTROL1: case CS35L56_ASP1_FRAME_CONTROL5: case CS35L56_ASP1_DATA_CONTROL1: case CS35L56_ASP1_DATA_CONTROL5: case CS35L56_DACPCM1_INPUT: case CS35L56_DACPCM2_INPUT: case CS35L56_ASP1TX1_INPUT: case CS35L56_ASP1TX2_INPUT: case CS35L56_ASP1TX3_INPUT: case CS35L56_ASP1TX4_INPUT: case CS35L56_DSP1RX1_INPUT: case CS35L56_DSP1RX2_INPUT: case CS35L56_SWIRE_DP3_CH1_INPUT: case CS35L56_SWIRE_DP3_CH2_INPUT: case CS35L56_SWIRE_DP3_CH3_INPUT: case CS35L56_SWIRE_DP3_CH4_INPUT: case CS35L56_IRQ1_CFG: case CS35L56_IRQ1_STATUS: case CS35L56_IRQ1_EINT_1 ... CS35L56_IRQ1_EINT_8: case CS35L56_IRQ1_EINT_18: case CS35L56_IRQ1_EINT_20: case CS35L56_IRQ1_MASK_1: case CS35L56_IRQ1_MASK_2: case CS35L56_IRQ1_MASK_4: case CS35L56_IRQ1_MASK_8: case CS35L56_IRQ1_MASK_18: case CS35L56_IRQ1_MASK_20: case CS35L56_DSP_VIRTUAL1_MBOX_1: case CS35L56_DSP_VIRTUAL1_MBOX_2: case CS35L56_DSP_VIRTUAL1_MBOX_3: case CS35L56_DSP_VIRTUAL1_MBOX_4: case CS35L56_DSP_VIRTUAL1_MBOX_5: case CS35L56_DSP_VIRTUAL1_MBOX_6: case CS35L56_DSP_VIRTUAL1_MBOX_7: case CS35L56_DSP_VIRTUAL1_MBOX_8: case CS35L56_DIE_STS1: case CS35L56_DIE_STS2: case CS35L56_DSP_RESTRICT_STS1: case CS35L56_DSP1_SYS_INFO_ID ... CS35L56_DSP1_SYS_INFO_END: case CS35L56_DSP1_AHBM_WINDOW_DEBUG_0: case CS35L56_DSP1_AHBM_WINDOW_DEBUG_1: case CS35L56_DSP1_SCRATCH1: case CS35L56_DSP1_SCRATCH2: case CS35L56_DSP1_SCRATCH3: case CS35L56_DSP1_SCRATCH4: returntrue; default: return cs35l56_is_dsp_memory(reg);
}
}
staticbool cs35l56_precious_reg(struct device *dev, unsignedint reg)
{ switch (reg) { case CS35L56_DSP1_XMEM_PACKED_0 ... CS35L56_DSP1_XMEM_PACKED_6143: case CS35L56_DSP1_YMEM_PACKED_0 ... CS35L56_DSP1_YMEM_PACKED_4604: case CS35L56_DSP1_PMEM_0 ... CS35L56_DSP1_PMEM_5114: returntrue; default: returnfalse;
}
}
staticbool cs35l56_common_volatile_reg(unsignedint reg)
{ switch (reg) { case CS35L56_DEVID: case CS35L56_REVID: case CS35L56_RELID: case CS35L56_OTPID: case CS35L56_SFT_RESET: case CS35L56_GLOBAL_ENABLES: /* owned by firmware */ case CS35L56_BLOCK_ENABLES: /* owned by firmware */ case CS35L56_BLOCK_ENABLES2: /* owned by firmware */ case CS35L56_REFCLK_INPUT: /* owned by firmware */ case CS35L56_GLOBAL_SAMPLE_RATE: /* owned by firmware */ case CS35L56_DACPCM1_INPUT: /* owned by firmware */ case CS35L56_DACPCM2_INPUT: /* owned by firmware */ case CS35L56_DSP1RX1_INPUT: /* owned by firmware */ case CS35L56_DSP1RX2_INPUT: /* owned by firmware */ case CS35L56_IRQ1_STATUS: case CS35L56_IRQ1_EINT_1 ... CS35L56_IRQ1_EINT_8: case CS35L56_IRQ1_EINT_18: case CS35L56_IRQ1_EINT_20: case CS35L56_DSP_VIRTUAL1_MBOX_1: case CS35L56_DSP_VIRTUAL1_MBOX_2: case CS35L56_DSP_VIRTUAL1_MBOX_3: case CS35L56_DSP_VIRTUAL1_MBOX_4: case CS35L56_DSP_VIRTUAL1_MBOX_5: case CS35L56_DSP_VIRTUAL1_MBOX_6: case CS35L56_DSP_VIRTUAL1_MBOX_7: case CS35L56_DSP_VIRTUAL1_MBOX_8: case CS35L56_DSP_RESTRICT_STS1: case CS35L56_DSP1_SYS_INFO_ID ... CS35L56_DSP1_SYS_INFO_END: case CS35L56_DSP1_AHBM_WINDOW_DEBUG_0: case CS35L56_DSP1_AHBM_WINDOW_DEBUG_1: case CS35L56_DSP1_SCRATCH1: case CS35L56_DSP1_SCRATCH2: case CS35L56_DSP1_SCRATCH3: case CS35L56_DSP1_SCRATCH4: returntrue; default: return cs35l56_is_dsp_memory(reg);
}
}
staticbool cs35l56_volatile_reg(struct device *dev, unsignedint reg)
{ switch (reg) { case CS35L56_MAIN_RENDER_USER_MUTE: case CS35L56_MAIN_RENDER_USER_VOLUME: case CS35L56_MAIN_POSTURE_NUMBER: returnfalse; default: return cs35l56_common_volatile_reg(reg);
}
}
staticbool cs35l63_volatile_reg(struct device *dev, unsignedint reg)
{ switch (reg) { case CS35L63_MAIN_RENDER_USER_MUTE: case CS35L63_MAIN_RENDER_USER_VOLUME: case CS35L63_MAIN_POSTURE_NUMBER: returnfalse; default: return cs35l56_common_volatile_reg(reg);
}
}
int cs35l56_mbox_send(struct cs35l56_base *cs35l56_base, unsignedint command)
{ unsignedint val; int ret;
void cs35l56_wait_control_port_ready(void)
{ /* Wait for control port to be ready (datasheet tIRS). */
usleep_range(CS35L56_CONTROL_PORT_READY_US, 2 * CS35L56_CONTROL_PORT_READY_US);
}
EXPORT_SYMBOL_NS_GPL(cs35l56_wait_control_port_ready, "SND_SOC_CS35L56_SHARED");
regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_EINT_20, &status20);
regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_MASK_20, &mask20);
status20 &= ~mask20; /* We don't want EINT20 but they default to unmasked: force mask */
regmap_write(cs35l56_base->regmap, CS35L56_IRQ1_MASK_20, 0xffffffff);
int cs35l56_is_fw_reload_needed(struct cs35l56_base *cs35l56_base)
{ unsignedint val; int ret;
/* *InsecuremodeFIRMWARE_MISSINGisclearedbytheBIOSloaderso *can'tbeusedheretotestformemoryretention. *Assumethattuningmustbere-loaded.
*/ if (cs35l56_base->secured) returntrue;
ret = pm_runtime_resume_and_get(cs35l56_base->dev); if (ret) {
dev_err(cs35l56_base->dev, "Failed to runtime_get: %d\n", ret); return ret;
}
ret = regmap_read(cs35l56_base->regmap,
cs35l56_base->fw_reg->prot_sts,
&val); if (ret)
dev_err(cs35l56_base->dev, "Failed to read PROTECTION_STATUS: %d\n", ret); else
ret = !!(val & CS35L56_FIRMWARE_MISSING);
staticconststruct reg_sequence cs35l56_hibernate_seq[] = { /* This must be the last register access */
REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_ALLOW_AUTO_HIBERNATE),
};
int cs35l56_runtime_suspend_common(struct cs35l56_base *cs35l56_base)
{ unsignedint val; int ret;
if (!cs35l56_base->init_done) return0;
/* Firmware must have entered a power-save state */
ret = regmap_read_poll_timeout(cs35l56_base->regmap,
cs35l56_base->fw_reg->transducer_actual_ps,
val, (val >= CS35L56_PS3),
CS35L56_PS3_POLL_US,
CS35L56_PS3_TIMEOUT_US); if (ret)
dev_warn(cs35l56_base->dev, "PS3 wait failed: %d\n", ret);
/* Clear BOOT_DONE so it can be used to detect a reboot */
regmap_write(cs35l56_base->regmap, CS35L56_IRQ1_EINT_4, CS35L56_OTP_BOOT_DONE_MASK);
if (!cs35l56_base->can_hibernate) {
regcache_cache_only(cs35l56_base->regmap, true);
dev_dbg(cs35l56_base->dev, "Suspended: no hibernate");
int cs35l56_runtime_resume_common(struct cs35l56_base *cs35l56_base, bool is_soundwire)
{ unsignedint val; int ret;
if (!cs35l56_base->init_done) return0;
if (!cs35l56_base->can_hibernate) goto out_sync;
/* Must be done before releasing cache-only */ if (!is_soundwire)
cs35l56_issue_wake_event(cs35l56_base);
out_sync:
ret = cs35l56_wait_for_firmware_boot(cs35l56_base); if (ret) {
dev_err(cs35l56_base->dev, "Hibernate wake failed: %d\n", ret); goto err;
}
regcache_cache_only(cs35l56_base->regmap, false);
ret = cs35l56_mbox_send(cs35l56_base, CS35L56_MBOX_CMD_PREVENT_AUTO_HIBERNATE); if (ret) goto err;
/* BOOT_DONE will be 1 if the amp reset */
regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_EINT_4, &val); if (val & CS35L56_OTP_BOOT_DONE_MASK) {
dev_dbg(cs35l56_base->dev, "Registers reset in suspend\n");
regcache_mark_dirty(cs35l56_base->regmap);
}
/* Wake source and *_BLOCKED interrupts default to unmasked, so mask them */
regmap_write(cs35l56_base->regmap, CS35L56_IRQ1_MASK_20, 0xffffffff);
regmap_update_bits(cs35l56_base->regmap, CS35L56_IRQ1_MASK_1,
CS35L56_AMP_SHORT_ERR_EINT1_MASK, 0);
regmap_update_bits(cs35l56_base->regmap, CS35L56_IRQ1_MASK_8,
CS35L56_TEMP_ERR_EINT1_MASK, 0);
int cs35l56_get_speaker_id(struct cs35l56_base *cs35l56_base)
{ struct gpio_descs *descs;
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) { return -ENOENT;
} elseif (IS_ERR(descs)) {
ret = PTR_ERR(descs); return dev_err_probe(cs35l56_base->dev, ret, "Failed to get spk-id-gpios\n");
}
speaker_id = 0; for (i = 0; i < descs->ndescs; i++) {
ret = gpiod_get_value_cansleep(descs->desc[i]); if (ret < 0) {
dev_err_probe(cs35l56_base->dev, ret, "Failed to read spk-id[%d]\n", i); goto err;
}
speaker_id |= (ret << i);
}
dev_dbg(cs35l56_base->dev, "Speaker ID = %d\n", speaker_id);
ret = speaker_id;
err:
gpiod_put_array(descs);
int cs35l56_get_bclk_freq_id(unsignedint freq)
{ int i;
if (freq == 0) return -EINVAL;
/* The BCLK frequency must be a valid PLL REFCLK */ for (i = 0; i < ARRAY_SIZE(cs35l56_bclk_valid_for_pll_freq_table); ++i) { if (cs35l56_bclk_valid_for_pll_freq_table[i] == freq) return i;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.