diff options
author | Tai Kuo <taikuo@google.com> | 2021-08-02 15:59:17 +0800 |
---|---|---|
committer | chasewu <chasewu@google.com> | 2021-09-08 10:29:57 +0800 |
commit | 2370e83abc93b307a0e1550d9565bc750a62d445 (patch) | |
tree | a3ce80a77a11cbf0e2f4c64672160723865e9781 /cs40l26/cs40l26-codec.c | |
parent | f70cd15574b2c93b7fa54517af9c7a1c0ec5a611 (diff) | |
download | amplifiers-2370e83abc93b307a0e1550d9565bc750a62d445.tar.gz |
cs40l26: merge CirrusLogic dsp v3.1.2 and cs40l26 v1.1.0
Branch: v5.10-cs40l26
Tag: cs40l26-v1.1.0_5.10
Files:
drivers/input/misc/cs40l26-i2c.c (No changes)
drivers/input/misc/cs40l26-spi.c (No changes)
drivers/input/misc/cs40l26-sysfs.c
drivers/input/misc/cs40l26-tables.c
drivers/input/misc/cs40l26.c
include/linux/mfd/cs40l26.h
sound/soc/codecs/cs40l26.c -> cs40l26-codec.c
Features:
- Increase A2H Volume Granularity
- Add more debug-level statements
- sysfs control to get amount of space left in wavetable
- DT control to set maximum boost peak current
- sysfs control to read die temperature
- sysfs control to swap firmware variants at runtime
- Load firmware synchronously
- Inverted streaming and waveform playback
- SVC enable for effects streamed via ASP
- Map Haptic Effects to GPI events
- Actuator Safe Mode workaround
- Remove support for A0 silicon
Bug fixes:
- Remove unused variables
- Cancel worker threads before deleting workqueue
commits:
c07047bd1087 ASoC: cs40l26: Add control to enable invert streaming data
7d0b08956875 input: cs40l26: Remove A0 silicon support
d6c20f8342fd input: cs40l26: Update firmware swap function
(Skip) 421500c4eb47 Documentation: cs40l26: Add option to load specified SVC tuning
a3fb83ecc3b3 input: cs40l26: Add option to load specified SVC tuning
736aa239110c ASoC: cs40l26: Add control to enable SVC for streaming data
7c060144b291 input: cs40l26: Implement actuator safe mode workaround
9b866d0e0362 input: cs40l26: Map Haptic Effects to GPI Events
e28e0a5131cc input: cs40l26: Add ability to invert waveform playback
961e4ba3a4bb input: cs40l26: Load firmware synchronously
23463ef1ab4a input: cs40l26: Add ability to swap firmware variants
05b2d67e3c66 input: cs40l26: Remove ENABLE/DISABLE macros
b6bd69389b17 input: cs40l26: Remove unneeded use of variable in cs40l26_pcm_ev
27af6399be8c input: cs40l26: Cancel worker threads before destroying workqueue
1794f854a2d0 input: cs40l26: Add control to read die temperature when DSP is active
50bf4051b3a8 input: cs40l26: Remove silicon rev. checks for algorithm IDs
(Skip) 3982e2db9db5 Documentation: cs40l26: Allow user to set peak boost current
756186d689c5 input: cs40l26: Allow user to set peak boost current
ed0f6bc72faa input: cs40l26: Control to read remaining space in wavetable
72510182f0f2 input: cs40l26: Use percentage value to set A0 gain
91d781c96e12 input: cs40l26: Make status registers readable via regmap
a8beb7e4c41f ASoC: cs40l26: Add dev_dbg statments to ALSA callbacks
c5b8320ebbce input: cs40l26: Add debug statements
17b3a65e18d1 input: cs40l26: Control to read Power On Sequence
8c4f68e0194a ASoC: cs40l26: Increase A2H Volume granularity
Branch: v5.10-cirrus-dsp-fw
Tag: cl-dsp-fw-v3.1.2_5.10
Files:
drivers/firmware/cirrus/cl_dsp.c
include/linux/firmware/cirrus/cl_dsp.h
Allocate array memory for .bin file data dynamically instead of using
a hard-coded value to avoid possibility of a kernel crash.
Allow firmware to load even if there are incompatibilities between
the expected firmware version, the loaded firmware, and the tuning
file revisions.
commits:
79a4a41e4fc6 firmware: cirrus: Allocate data array dynamically
19140c2d644b firmware: cirrus: Loosen restrictions on firmware loading
8e02f2e42990 firmware: cirrus: Don't explicitly free coefficient parent name
Bug: 191658078
Bug: 180110149
Bug: 194540033
Bug: 193793095
Test: Check idlcli vibrator commands.
Test: Back EMF for internal calibration.
Test: Firmware swap.
Signed-off-by: Tai Kuo <taikuo@google.com>
Change-Id: I7db82ce23663772a83e69490b88cfb47e4bf93f3
Diffstat (limited to 'cs40l26/cs40l26-codec.c')
-rw-r--r-- | cs40l26/cs40l26-codec.c | 165 |
1 files changed, 133 insertions, 32 deletions
diff --git a/cs40l26/cs40l26-codec.c b/cs40l26/cs40l26-codec.c index 9c14b9f..c19d2e9 100644 --- a/cs40l26/cs40l26-codec.c +++ b/cs40l26/cs40l26-codec.c @@ -60,7 +60,7 @@ static int cs40l26_swap_ext_clk(struct cs40l26_codec *codec, u8 clk_src) } ret = regmap_update_bits(regmap, CS40L26_REFCLK_INPUT, - CS40L26_PLL_REFCLK_OPEN_LOOP_MASK, CS40L26_ENABLE << + CS40L26_PLL_REFCLK_OPEN_LOOP_MASK, 1 << CS40L26_PLL_REFCLK_OPEN_LOOP_SHIFT); if (ret) { dev_err(dev, "Failed to set Open-Loop PLL\n"); @@ -77,7 +77,7 @@ static int cs40l26_swap_ext_clk(struct cs40l26_codec *codec, u8 clk_src) } ret = regmap_update_bits(regmap, CS40L26_REFCLK_INPUT, - CS40L26_PLL_REFCLK_OPEN_LOOP_MASK, CS40L26_DISABLE << + CS40L26_PLL_REFCLK_OPEN_LOOP_MASK, 0 << CS40L26_PLL_REFCLK_OPEN_LOOP_SHIFT); if (ret) dev_err(dev, "Failed to close PLL loop\n"); @@ -94,6 +94,9 @@ static int cs40l26_clk_en(struct snd_soc_dapm_widget *w, struct device *dev = cs40l26->dev; int ret; + dev_info(dev, "%s: %s\n", __func__, + event == SND_SOC_DAPM_POST_PMU ? "PMU" : "PMD"); + switch (event) { case SND_SOC_DAPM_POST_PMU: mutex_lock(&cs40l26->lock); @@ -135,6 +138,9 @@ static int cs40l26_a2h_ev(struct snd_soc_dapm_widget *w, int ret; u32 reg; + dev_dbg(dev, "%s: %s\n", __func__, + event == SND_SOC_DAPM_POST_PMU ? "PMU" : "PMD"); + ret = cl_dsp_get_reg(cs40l26->dsp, "A2HEN", CL_DSP_XM_UNPACKED_TYPE, CS40L26_A2H_ALGO_ID, ®); if (ret) @@ -163,9 +169,9 @@ static int cs40l26_a2h_ev(struct snd_soc_dapm_widget *w, if (ret) return ret; } - return regmap_write(cs40l26->regmap, reg, CS40L26_ENABLE); + return regmap_write(cs40l26->regmap, reg, 1); case SND_SOC_DAPM_PRE_PMD: - return regmap_write(cs40l26->regmap, reg, CS40L26_DISABLE); + return regmap_write(cs40l26->regmap, reg, 0); default: dev_err(dev, "Invalid A2H event: %d\n", event); return -EINVAL; @@ -181,9 +187,12 @@ static int cs40l26_pcm_ev(struct snd_soc_dapm_widget *w, struct device *dev = cs40l26->dev; u32 asp_en_mask = CS40L26_ASP_TX1_EN_MASK | CS40L26_ASP_TX2_EN_MASK | CS40L26_ASP_RX1_EN_MASK | CS40L26_ASP_RX2_EN_MASK; - u32 asp_enables; + u32 asp_enables, reg; int ret; + dev_info(dev, "%s: %s\n", __func__, + event == SND_SOC_DAPM_POST_PMU ? "PMU" : "PMD"); + switch (event) { case SND_SOC_DAPM_POST_PMU: ret = regmap_update_bits(regmap, CS40L26_DACPCM1_INPUT, @@ -200,10 +209,9 @@ static int cs40l26_pcm_ev(struct snd_soc_dapm_widget *w, return ret; } - asp_enables = CS40L26_ENABLE | (CS40L26_ENABLE << - CS40L26_ASP_TX2_EN_SHIFT) | (CS40L26_ENABLE << - CS40L26_ASP_RX1_EN_SHIFT) | (CS40L26_ENABLE << - CS40L26_ASP_RX2_EN_SHIFT); + asp_enables = 1 | (1 << CS40L26_ASP_TX2_EN_SHIFT) + | (1 << CS40L26_ASP_RX1_EN_SHIFT) + | (1 << CS40L26_ASP_RX2_EN_SHIFT); ret = regmap_update_bits(regmap, CS40L26_ASP_ENABLES1, asp_en_mask, asp_enables); @@ -224,6 +232,28 @@ static int cs40l26_pcm_ev(struct snd_soc_dapm_widget *w, if (ret) return ret; + ret = cl_dsp_get_reg(cs40l26->dsp, "FLAGS", + CL_DSP_XM_UNPACKED_TYPE, CS40L26_EXT_ALGO_ID, ®); + if (ret) + return ret; + + ret = regmap_write(regmap, reg, codec->svc_for_streaming_data); + if (ret) { + dev_err(dev, "Failed to specify SVC for streaming\n"); + return ret; + } + + ret = cl_dsp_get_reg(cs40l26->dsp, "SOURCE_INVERT", + CL_DSP_XM_UNPACKED_TYPE, CS40L26_EXT_ALGO_ID, ®); + if (ret) + return ret; + + ret = regmap_write(regmap, reg, codec->invert_streaming_data); + if (ret) { + dev_err(dev, "Failed to specify SVC for streaming\n"); + return ret; + } + ret = cs40l26_ack_write(cs40l26, CS40L26_DSP_VIRTUAL1_MBOX_1, CS40L26_DSP_MBOX_CMD_START_I2S, CS40L26_DSP_MBOX_RESET); @@ -239,13 +269,8 @@ static int cs40l26_pcm_ev(struct snd_soc_dapm_widget *w, if (ret) return ret; - asp_enables = CS40L26_DISABLE | (CS40L26_DISABLE << - CS40L26_ASP_TX2_EN_SHIFT) | (CS40L26_DISABLE << - CS40L26_ASP_RX1_EN_SHIFT) | (CS40L26_DISABLE << - CS40L26_ASP_RX2_EN_SHIFT); - ret = regmap_update_bits(regmap, CS40L26_ASP_ENABLES1, - asp_en_mask, asp_enables); + asp_en_mask, 0); if (ret) { dev_err(dev, "Failed to clear ASPTX1 input\n"); return ret; @@ -264,6 +289,83 @@ static int cs40l26_pcm_ev(struct snd_soc_dapm_widget *w, return ret; } +static int cs40l26_svc_for_streaming_data_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct cs40l26_codec *codec = + snd_soc_component_get_drvdata(snd_soc_kcontrol_component(kcontrol)); + struct cs40l26_private *cs40l26 = codec->core; + + mutex_lock(&cs40l26->lock); + + if (codec->svc_for_streaming_data) + ucontrol->value.enumerated.item[0] = 1; + else + ucontrol->value.enumerated.item[0] = 0; + + mutex_unlock(&cs40l26->lock); + + return 0; +} + +static int cs40l26_svc_for_streaming_data_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct cs40l26_codec *codec = + snd_soc_component_get_drvdata(snd_soc_kcontrol_component(kcontrol)); + struct cs40l26_private *cs40l26 = codec->core; + + mutex_lock(&cs40l26->lock); + + if (ucontrol->value.enumerated.item[0]) + codec->svc_for_streaming_data = true; + else + codec->svc_for_streaming_data = false; + + mutex_unlock(&cs40l26->lock); + + return 0; +} + +static int cs40l26_invert_streaming_data_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct cs40l26_codec *codec = + snd_soc_component_get_drvdata(snd_soc_kcontrol_component(kcontrol)); + struct cs40l26_private *cs40l26 = codec->core; + + mutex_lock(&cs40l26->lock); + + if (codec->invert_streaming_data) + ucontrol->value.enumerated.item[0] = 1; + else + ucontrol->value.enumerated.item[0] = 0; + + mutex_unlock(&cs40l26->lock); + + return 0; +} + +static int cs40l26_invert_streaming_data_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct cs40l26_codec *codec = + snd_soc_component_get_drvdata(snd_soc_kcontrol_component(kcontrol)); + struct cs40l26_private *cs40l26 = codec->core; + + mutex_lock(&cs40l26->lock); + + if (ucontrol->value.enumerated.item[0]) + codec->invert_streaming_data = true; + else + codec->invert_streaming_data = false; + + mutex_unlock(&cs40l26->lock); + + return 0; +} + + static int cs40l26_tuning_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -302,7 +404,7 @@ static int cs40l26_tuning_put(struct snd_kcontrol *kcontrol, return 0; } -static int cs40l26_volume_get(struct snd_kcontrol *kcontrol, +static int cs40l26_a2h_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct cs40l26_codec *codec = @@ -321,17 +423,9 @@ static int cs40l26_volume_get(struct snd_kcontrol *kcontrol, pm_runtime_get_sync(dev); ret = regmap_read(regmap, reg, &val); - if (ret) { + if (ret) dev_err(dev, "Failed to get VOLUMELEVEL\n"); - goto err_pm; - } - - if (val == CS40L26_VOLUME_MAX) - val = CS40L26_VOLUME_MAX_STEPS; - else - val /= CS40L26_VOLUME_STEP_SIZE; -err_pm: pm_runtime_mark_last_busy(dev); pm_runtime_put_autosuspend(dev); @@ -340,7 +434,7 @@ err_pm: return ret; } -static int cs40l26_volume_put(struct snd_kcontrol *kcontrol, +static int cs40l26_a2h_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct cs40l26_codec *codec = @@ -356,11 +450,12 @@ static int cs40l26_volume_put(struct snd_kcontrol *kcontrol, if (ret) return ret; - val = ucontrol->value.integer.value[0]; - if (val == CS40L26_VOLUME_MAX_STEPS) - val = CS40L26_VOLUME_MAX; + if (ucontrol->value.integer.value[0] > CS40L26_A2H_VOLUME_MAX) + val = CS40L26_A2H_VOLUME_MAX; + else if (ucontrol->value.integer.value[0] < 0) + val = 0; else - val *= CS40L26_VOLUME_STEP_SIZE; + val = ucontrol->value.integer.value[0]; pm_runtime_get_sync(dev); @@ -377,8 +472,14 @@ static int cs40l26_volume_put(struct snd_kcontrol *kcontrol, static const struct snd_kcontrol_new cs40l26_controls[] = { SOC_SINGLE_EXT("A2H Tuning", 0, 0, CS40L26_A2H_MAX_TUNINGS, 0, cs40l26_tuning_get, cs40l26_tuning_put), - SOC_SINGLE_EXT("A2H Volume", 0, 0, CS40L26_VOLUME_MAX_STEPS, 0, - cs40l26_volume_get, cs40l26_volume_put), + SOC_SINGLE_EXT("A2H Volume", 0, 0, CS40L26_A2H_VOLUME_MAX, 0, + cs40l26_a2h_volume_get, cs40l26_a2h_volume_put), + SOC_SINGLE_EXT("SVC for streaming data", 0, 0, 1, 0, + cs40l26_svc_for_streaming_data_get, + cs40l26_svc_for_streaming_data_put), + SOC_SINGLE_EXT("Invert streaming data", 0, 0, 1, 0, + cs40l26_invert_streaming_data_get, + cs40l26_invert_streaming_data_put), }; static const char * const cs40l26_out_mux_texts[] = { "Off", "PCM", "A2H" }; |