mirror of
https://github.com/edk2-porting/linux-next.git
synced 2025-01-17 18:14:34 +08:00
Add low power hibernation support to cs35l41
Merge series from Charles Keepax <ckeepax@opensource.cirrus.com>: This patch series adds support for the low power hibernation feature on cs35l41. This allows the DSP memory to be retained whilst the device enters a very low power state.
This commit is contained in:
commit
570010b82e
@ -2744,10 +2744,16 @@ EXPORT_SYMBOL_GPL(cs_dsp_stop);
|
||||
|
||||
static int cs_dsp_halo_start_core(struct cs_dsp *dsp)
|
||||
{
|
||||
return regmap_update_bits(dsp->regmap,
|
||||
dsp->base + HALO_CCM_CORE_CONTROL,
|
||||
HALO_CORE_RESET | HALO_CORE_EN,
|
||||
HALO_CORE_RESET | HALO_CORE_EN);
|
||||
int ret;
|
||||
|
||||
ret = regmap_update_bits(dsp->regmap, dsp->base + HALO_CCM_CORE_CONTROL,
|
||||
HALO_CORE_RESET | HALO_CORE_EN,
|
||||
HALO_CORE_RESET | HALO_CORE_EN);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return regmap_update_bits(dsp->regmap, dsp->base + HALO_CCM_CORE_CONTROL,
|
||||
HALO_CORE_RESET, 0);
|
||||
}
|
||||
|
||||
static void cs_dsp_halo_stop_core(struct cs_dsp *dsp)
|
||||
|
@ -22,6 +22,8 @@
|
||||
static const struct i2c_device_id cs35l41_id_i2c[] = {
|
||||
{ "cs35l40", 0 },
|
||||
{ "cs35l41", 0 },
|
||||
{ "cs35l51", 0 },
|
||||
{ "cs35l53", 0 },
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -20,6 +20,11 @@ static const struct reg_default cs35l41_reg[] = {
|
||||
{ CS35L41_PWR_CTRL2, 0x00000000 },
|
||||
{ CS35L41_PWR_CTRL3, 0x01000010 },
|
||||
{ CS35L41_GPIO_PAD_CONTROL, 0x00000000 },
|
||||
{ CS35L41_GLOBAL_CLK_CTRL, 0x00000003 },
|
||||
{ CS35L41_TST_FS_MON0, 0x00020016 },
|
||||
{ CS35L41_BSTCVRT_COEFF, 0x00002424 },
|
||||
{ CS35L41_BSTCVRT_SLOPE_LBST, 0x00007500 },
|
||||
{ CS35L41_BSTCVRT_PEAK_CUR, 0x0000004A },
|
||||
{ CS35L41_SP_ENABLES, 0x00000000 },
|
||||
{ CS35L41_SP_RATE_CTRL, 0x00000028 },
|
||||
{ CS35L41_SP_FORMAT, 0x18180200 },
|
||||
@ -48,11 +53,16 @@ static const struct reg_default cs35l41_reg[] = {
|
||||
{ CS35L41_WKFET_CFG, 0x00000111 },
|
||||
{ CS35L41_NG_CFG, 0x00000033 },
|
||||
{ CS35L41_AMP_GAIN_CTRL, 0x00000000 },
|
||||
{ CS35L41_IRQ1_MASK1, 0xFFFFFFFF },
|
||||
{ CS35L41_IRQ1_MASK2, 0xFFFFFFFF },
|
||||
{ CS35L41_IRQ1_MASK3, 0xFFFF87FF },
|
||||
{ CS35L41_IRQ1_MASK4, 0xFEFFFFFF },
|
||||
{ CS35L41_GPIO1_CTRL1, 0xE1000001 },
|
||||
{ CS35L41_GPIO2_CTRL1, 0xE1000001 },
|
||||
{ CS35L41_MIXER_NGATE_CFG, 0x00000000 },
|
||||
{ CS35L41_MIXER_NGATE_CH1_CFG, 0x00000303 },
|
||||
{ CS35L41_MIXER_NGATE_CH2_CFG, 0x00000303 },
|
||||
{ CS35L41_DSP1_CCM_CORE_CTRL, 0x00000101 },
|
||||
};
|
||||
|
||||
static bool cs35l41_readable_reg(struct device *dev, unsigned int reg)
|
||||
@ -84,6 +94,7 @@ static bool cs35l41_readable_reg(struct device *dev, unsigned int reg)
|
||||
case CS35L41_DSP_CLK_CTRL:
|
||||
case CS35L41_GLOBAL_CLK_CTRL:
|
||||
case CS35L41_DATA_FS_SEL:
|
||||
case CS35L41_TST_FS_MON0:
|
||||
case CS35L41_MDSYNC_EN:
|
||||
case CS35L41_MDSYNC_TX_ID:
|
||||
case CS35L41_MDSYNC_PWR_CTRL:
|
||||
@ -342,7 +353,10 @@ static bool cs35l41_readable_reg(struct device *dev, unsigned int reg)
|
||||
static bool cs35l41_precious_reg(struct device *dev, unsigned int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case CS35L41_TEST_KEY_CTL:
|
||||
case CS35L41_USER_KEY_CTL:
|
||||
case CS35L41_OTP_MEM0 ... CS35L41_OTP_MEM31:
|
||||
case CS35L41_TST_FS_MON0:
|
||||
case CS35L41_DSP1_XMEM_PACK_0 ... CS35L41_DSP1_XMEM_PACK_3068:
|
||||
case CS35L41_DSP1_YMEM_PACK_0 ... CS35L41_DSP1_YMEM_PACK_1532:
|
||||
case CS35L41_DSP1_PMEM_0 ... CS35L41_DSP1_PMEM_5114:
|
||||
@ -359,6 +373,9 @@ static bool cs35l41_volatile_reg(struct device *dev, unsigned int reg)
|
||||
case CS35L41_SFT_RESET:
|
||||
case CS35L41_FABID:
|
||||
case CS35L41_REVID:
|
||||
case CS35L41_OTPID:
|
||||
case CS35L41_TEST_KEY_CTL:
|
||||
case CS35L41_USER_KEY_CTL:
|
||||
case CS35L41_DTEMP_EN:
|
||||
case CS35L41_IRQ1_STATUS:
|
||||
case CS35L41_IRQ1_STATUS1:
|
||||
@ -369,17 +386,6 @@ static bool cs35l41_volatile_reg(struct device *dev, unsigned int reg)
|
||||
case CS35L41_IRQ1_RAW_STATUS2:
|
||||
case CS35L41_IRQ1_RAW_STATUS3:
|
||||
case CS35L41_IRQ1_RAW_STATUS4:
|
||||
case CS35L41_IRQ1_FRC1:
|
||||
case CS35L41_IRQ1_FRC2:
|
||||
case CS35L41_IRQ1_FRC3:
|
||||
case CS35L41_IRQ1_FRC4:
|
||||
case CS35L41_IRQ1_EDGE1:
|
||||
case CS35L41_IRQ1_EDGE4:
|
||||
case CS35L41_IRQ1_POL1:
|
||||
case CS35L41_IRQ1_POL2:
|
||||
case CS35L41_IRQ1_POL3:
|
||||
case CS35L41_IRQ1_POL4:
|
||||
case CS35L41_IRQ1_DB3:
|
||||
case CS35L41_IRQ2_STATUS:
|
||||
case CS35L41_IRQ2_STATUS1:
|
||||
case CS35L41_IRQ2_STATUS2:
|
||||
@ -389,54 +395,7 @@ static bool cs35l41_volatile_reg(struct device *dev, unsigned int reg)
|
||||
case CS35L41_IRQ2_RAW_STATUS2:
|
||||
case CS35L41_IRQ2_RAW_STATUS3:
|
||||
case CS35L41_IRQ2_RAW_STATUS4:
|
||||
case CS35L41_IRQ2_FRC1:
|
||||
case CS35L41_IRQ2_FRC2:
|
||||
case CS35L41_IRQ2_FRC3:
|
||||
case CS35L41_IRQ2_FRC4:
|
||||
case CS35L41_IRQ2_EDGE1:
|
||||
case CS35L41_IRQ2_EDGE4:
|
||||
case CS35L41_IRQ2_POL1:
|
||||
case CS35L41_IRQ2_POL2:
|
||||
case CS35L41_IRQ2_POL3:
|
||||
case CS35L41_IRQ2_POL4:
|
||||
case CS35L41_IRQ2_DB3:
|
||||
case CS35L41_GPIO_STATUS1:
|
||||
case CS35L41_OTP_TRIM_1:
|
||||
case CS35L41_OTP_TRIM_2:
|
||||
case CS35L41_OTP_TRIM_3:
|
||||
case CS35L41_OTP_TRIM_4:
|
||||
case CS35L41_OTP_TRIM_5:
|
||||
case CS35L41_OTP_TRIM_6:
|
||||
case CS35L41_OTP_TRIM_7:
|
||||
case CS35L41_OTP_TRIM_8:
|
||||
case CS35L41_OTP_TRIM_9:
|
||||
case CS35L41_OTP_TRIM_10:
|
||||
case CS35L41_OTP_TRIM_11:
|
||||
case CS35L41_OTP_TRIM_12:
|
||||
case CS35L41_OTP_TRIM_13:
|
||||
case CS35L41_OTP_TRIM_14:
|
||||
case CS35L41_OTP_TRIM_15:
|
||||
case CS35L41_OTP_TRIM_16:
|
||||
case CS35L41_OTP_TRIM_17:
|
||||
case CS35L41_OTP_TRIM_18:
|
||||
case CS35L41_OTP_TRIM_19:
|
||||
case CS35L41_OTP_TRIM_20:
|
||||
case CS35L41_OTP_TRIM_21:
|
||||
case CS35L41_OTP_TRIM_22:
|
||||
case CS35L41_OTP_TRIM_23:
|
||||
case CS35L41_OTP_TRIM_24:
|
||||
case CS35L41_OTP_TRIM_25:
|
||||
case CS35L41_OTP_TRIM_26:
|
||||
case CS35L41_OTP_TRIM_27:
|
||||
case CS35L41_OTP_TRIM_28:
|
||||
case CS35L41_OTP_TRIM_29:
|
||||
case CS35L41_OTP_TRIM_30:
|
||||
case CS35L41_OTP_TRIM_31:
|
||||
case CS35L41_OTP_TRIM_32:
|
||||
case CS35L41_OTP_TRIM_33:
|
||||
case CS35L41_OTP_TRIM_34:
|
||||
case CS35L41_OTP_TRIM_35:
|
||||
case CS35L41_OTP_TRIM_36:
|
||||
case CS35L41_DSP_MBOX_1 ... CS35L41_DSP_VIRT2_MBOX_8:
|
||||
case CS35L41_DSP1_XMEM_PACK_0 ... CS35L41_DSP1_XMEM_PACK_3068:
|
||||
case CS35L41_DSP1_XMEM_UNPACK32_0 ... CS35L41_DSP1_XMEM_UNPACK32_2046:
|
||||
@ -445,7 +404,11 @@ static bool cs35l41_volatile_reg(struct device *dev, unsigned int reg)
|
||||
case CS35L41_DSP1_YMEM_UNPACK32_0 ... CS35L41_DSP1_YMEM_UNPACK32_1022:
|
||||
case CS35L41_DSP1_YMEM_UNPACK24_0 ... CS35L41_DSP1_YMEM_UNPACK24_2045:
|
||||
case CS35L41_DSP1_PMEM_0 ... CS35L41_DSP1_PMEM_5114:
|
||||
case CS35L41_DSP1_CCM_CORE_CTRL ... CS35L41_DSP1_WDT_STATUS:
|
||||
case CS35L41_DSP1_SCRATCH1:
|
||||
case CS35L41_DSP1_SCRATCH2:
|
||||
case CS35L41_DSP1_SCRATCH3:
|
||||
case CS35L41_DSP1_SCRATCH4:
|
||||
case CS35L41_DSP1_CCM_CLK_OVERRIDE ... CS35L41_DSP1_WDT_STATUS:
|
||||
case CS35L41_OTP_MEM0 ... CS35L41_OTP_MEM31:
|
||||
return true;
|
||||
default:
|
||||
|
@ -20,6 +20,8 @@
|
||||
static const struct spi_device_id cs35l41_id_spi[] = {
|
||||
{ "cs35l40", 0 },
|
||||
{ "cs35l41", 0 },
|
||||
{ "cs35l51", 0 },
|
||||
{ "cs35l53", 0 },
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -181,17 +181,21 @@ static SOC_ENUM_SINGLE_DECL(pcm_sft_ramp,
|
||||
static int cs35l41_dsp_preload_ev(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol, int event)
|
||||
{
|
||||
struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
|
||||
struct cs35l41_private *cs35l41 = snd_soc_component_get_drvdata(component);
|
||||
int ret;
|
||||
|
||||
switch (event) {
|
||||
case SND_SOC_DAPM_PRE_PMU:
|
||||
return wm_adsp_early_event(w, kcontrol, event);
|
||||
case SND_SOC_DAPM_PRE_PMD:
|
||||
ret = wm_adsp_early_event(w, kcontrol, event);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (cs35l41->dsp.cs_dsp.running) {
|
||||
ret = wm_adsp_event(w, kcontrol, event);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return wm_adsp_event(w, kcontrol, event);
|
||||
return wm_adsp_early_event(w, kcontrol, event);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@ -1338,8 +1342,6 @@ int cs35l41_probe(struct cs35l41_private *cs35l41,
|
||||
ret = devm_request_threaded_irq(cs35l41->dev, cs35l41->irq, NULL, cs35l41_irq,
|
||||
IRQF_ONESHOT | IRQF_SHARED | irq_pol,
|
||||
"cs35l41", cs35l41);
|
||||
|
||||
/* CS35L41 needs INT for PDN_DONE */
|
||||
if (ret != 0) {
|
||||
dev_err(cs35l41->dev, "Failed to request IRQ: %d\n", ret);
|
||||
goto err;
|
||||
|
@ -896,11 +896,12 @@ int wm_adsp2_preloader_put(struct snd_kcontrol *kcontrol,
|
||||
struct wm_adsp *dsp = &dsps[mc->shift - 1];
|
||||
char preload[32];
|
||||
|
||||
if (dsp->preloaded == ucontrol->value.integer.value[0])
|
||||
return 0;
|
||||
|
||||
snprintf(preload, ARRAY_SIZE(preload), "%s Preload", dsp->cs_dsp.name);
|
||||
|
||||
dsp->preloaded = ucontrol->value.integer.value[0];
|
||||
|
||||
if (ucontrol->value.integer.value[0])
|
||||
if (ucontrol->value.integer.value[0] || dsp->toggle_preload)
|
||||
snd_soc_component_force_enable_pin(component, preload);
|
||||
else
|
||||
snd_soc_component_disable_pin(component, preload);
|
||||
@ -909,6 +910,13 @@ int wm_adsp2_preloader_put(struct snd_kcontrol *kcontrol,
|
||||
|
||||
flush_work(&dsp->boot_work);
|
||||
|
||||
dsp->preloaded = ucontrol->value.integer.value[0];
|
||||
|
||||
if (dsp->toggle_preload) {
|
||||
snd_soc_component_disable_pin(component, preload);
|
||||
snd_soc_dapm_sync(dapm);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(wm_adsp2_preloader_put);
|
||||
|
@ -41,6 +41,14 @@ struct wm_adsp {
|
||||
|
||||
struct list_head compr_list;
|
||||
struct list_head buffer_list;
|
||||
|
||||
/*
|
||||
* Flag indicating the preloader widget only needs power toggled
|
||||
* on state change rather than held on for the duration of the
|
||||
* preload, useful for devices that can retain firmware memory
|
||||
* across power down.
|
||||
*/
|
||||
bool toggle_preload;
|
||||
};
|
||||
|
||||
#define WM_ADSP1(wname, num) \
|
||||
|
Loading…
Reference in New Issue
Block a user