diff options
author | Tai Kuo <taikuo@google.com> | 2023-02-15 11:29:26 +0800 |
---|---|---|
committer | Tai Kuo <taikuo@google.com> | 2023-02-22 21:41:05 +0800 |
commit | 0b90564a44e746d78ac1717f7554d1d3be1be948 (patch) | |
tree | 15d9d2279aa96ca013913bc65762a8eaeadaf51b | |
parent | ebfdb59865dd0c7483601fb7f37bad0eea7c249b (diff) | |
download | amplifiers-0b90564a44e746d78ac1717f7554d1d3be1be948.tar.gz |
cs40l26: merge cs40l26 v6.0.1
Branches: v5.15-cs40l26
Tags: cs40l26-v6.0.1_5.15
Files:
Documentation/devicetree/bindings/input/cs40l26.yaml
drivers/firmware/cirrus/cl_dsp-debugfs.c (No changes)
drivers/firmware/cirrus/cl_dsp.c (No changes)
include/linux/firmware/cirrus/cl_dsp.h (No changes)
drivers/input/misc/cs40l26-debugfs.c
drivers/input/misc/cs40l26-i2c.c (No changes)
drivers/input/misc/cs40l26-spi.c (No changes)
drivers/input/misc/cs40l26-sysfs.c (No changes)
drivers/input/misc/cs40l26-tables.c (No changes)
drivers/input/misc/cs40l26.c
include/linux/mfd/cs40l26.h
sound/soc/codecs/cs40l26.c -> cs40l26-codec.c
Features:
- Add devicetree parameters for mapping default
GPI events to particular effects
- Rename certain mixer controls for more intuitive usage
Bug fixes:
- Allow CL DSP debugfs directory to be created when firmware
loading is deferred via the devicetree
Commits: 9c56d30 input: cs40l26: Enable cl_dsp debugfs for deferred F/W case
b967746 Documentation: cs40l26: Map GPI effects via devicetree
e991944 input: cs40l26: Map GPI effects via devicetree
02c7093 ASoC: cs40l26: Reconfigure mixer controls
Bug: 270109840
Test: Copy texts and adjust alarm
Test: NFC, dumpstate, keyboard vibration
Test: idlcli commands
Test: Switch firmware continuous
Test: Switch firmware and check the first tick effect
Test: atest PtsVibratorHalTestSuite \
PtsHapticsTestCases \
VibratorHalCs40l26TestSuite \
VtsHalVibratorManagerTargetTest \
VtsHalVibratorTargetTest \
android.os.cts.VibratorTest \
android.os.cts.VibratorManagerTest \
android.os.cts.VibrationEffectTest \
android.os.cts.VibrationAttributesTest \
android.os.cts.CombinedVibrationTest
Change-Id: I9ef639e7fb4adc7eb0d99c8c0cec15d086d50096
Signed-off-by: Tai Kuo <taikuo@google.com>
-rw-r--r-- | cs40l26/cs40l26-codec.c | 71 | ||||
-rw-r--r-- | cs40l26/cs40l26-debugfs.c | 15 | ||||
-rw-r--r-- | cs40l26/cs40l26.c | 47 | ||||
-rw-r--r-- | cs40l26/cs40l26.h | 12 | ||||
-rw-r--r-- | cs40l26/cs40l26.yaml | 13 |
5 files changed, 106 insertions, 52 deletions
diff --git a/cs40l26/cs40l26-codec.c b/cs40l26/cs40l26-codec.c index b1c8b6e..9272ef2 100644 --- a/cs40l26/cs40l26-codec.c +++ b/cs40l26/cs40l26-codec.c @@ -132,7 +132,7 @@ static int cs40l26_clk_en(struct snd_soc_dapm_widget *w, return 0; } -static int cs40l26_a2h_ev(struct snd_soc_dapm_widget *w, +static int cs40l26_dsp_tx(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct cs40l26_codec *codec = snd_soc_component_get_drvdata(snd_soc_dapm_to_component(w->dapm)); @@ -145,8 +145,8 @@ static int cs40l26_a2h_ev(struct snd_soc_dapm_widget *w, dev_dbg(dev, "%s: %s\n", __func__, event == SND_SOC_DAPM_POST_PMU ? "PMU" : "PMD"); - if (codec->bypass_dsp) { - dev_err(dev, "Cannot apply A2H if DSP is bypassed\n"); + if (codec->dsp_bypass) { + dev_err(dev, "Cannot use A2H while bypassing DSP\n"); return -EPERM; } @@ -195,7 +195,7 @@ static int cs40l26_a2h_ev(struct snd_soc_dapm_widget *w, } } -static int cs40l26_pcm_ev(struct snd_soc_dapm_widget *w, +static int cs40l26_asp_rx(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct cs40l26_codec *codec = snd_soc_component_get_drvdata(snd_soc_dapm_to_component(w->dapm)); @@ -213,7 +213,7 @@ static int cs40l26_pcm_ev(struct snd_soc_dapm_widget *w, mutex_lock(&cs40l26->lock); - data_src = codec->bypass_dsp ? CS40L26_DATA_SRC_ASPRX1 : + data_src = codec->dsp_bypass ? CS40L26_DATA_SRC_ASPRX1 : CS40L26_DATA_SRC_DSP1TX1; switch (event) { @@ -309,7 +309,7 @@ pm_err: return ret; } -static int cs40l26_bypass_get(struct snd_kcontrol *kcontrol, +static int cs40l26_dsp_bypass_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct cs40l26_codec *codec = @@ -318,7 +318,7 @@ static int cs40l26_bypass_get(struct snd_kcontrol *kcontrol, mutex_lock(&cs40l26->lock); - if (codec->bypass_dsp) + if (codec->dsp_bypass) ucontrol->value.enumerated.item[0] = 1; else ucontrol->value.enumerated.item[0] = 0; @@ -328,7 +328,7 @@ static int cs40l26_bypass_get(struct snd_kcontrol *kcontrol, return 0; } -static int cs40l26_bypass_put(struct snd_kcontrol *kcontrol, +static int cs40l26_dsp_bypass_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct cs40l26_codec *codec = @@ -338,16 +338,16 @@ static int cs40l26_bypass_put(struct snd_kcontrol *kcontrol, mutex_lock(&cs40l26->lock); if (ucontrol->value.enumerated.item[0]) - codec->bypass_dsp = true; + codec->dsp_bypass = true; else - codec->bypass_dsp = false; + codec->dsp_bypass = false; mutex_unlock(&cs40l26->lock); return 0; } -static int cs40l26_svc_for_streaming_data_get(struct snd_kcontrol *kcontrol, +static int cs40l26_svc_en_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct cs40l26_codec *codec = @@ -373,7 +373,7 @@ static int cs40l26_svc_for_streaming_data_get(struct snd_kcontrol *kcontrol, goto pm_err; } - if (val & CS40L26_SVC_FOR_STREAMING_MASK) + if (val & CS40L26_SVC_EN_MASK) ucontrol->value.enumerated.item[0] = 1; else ucontrol->value.enumerated.item[0] = 0; @@ -384,7 +384,7 @@ pm_err: return ret; } -static int cs40l26_svc_for_streaming_data_put(struct snd_kcontrol *kcontrol, +static int cs40l26_svc_en_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_dapm_context *dapm = @@ -409,7 +409,7 @@ static int cs40l26_svc_for_streaming_data_put(struct snd_kcontrol *kcontrol, snd_soc_dapm_mutex_lock(dapm); ret = regmap_update_bits(regmap, reg, - CS40L26_SVC_FOR_STREAMING_MASK, + CS40L26_SVC_EN_MASK, ucontrol->value.enumerated.item[0]); if (ret) dev_err(cs40l26->dev, "Failed to specify SVC for streaming\n"); @@ -531,7 +531,7 @@ static int cs40l26_tuning_put(struct snd_kcontrol *kcontrol, return 0; } -static int cs40l26_a2h_volume_get(struct snd_kcontrol *kcontrol, +static int cs40l26_a2h_level_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct cs40l26_codec *codec = @@ -565,7 +565,7 @@ pm_err: return ret; } -static int cs40l26_a2h_volume_put(struct snd_kcontrol *kcontrol, +static int cs40l26_a2h_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_dapm_context *dapm = @@ -589,8 +589,8 @@ static int cs40l26_a2h_volume_put(struct snd_kcontrol *kcontrol, snd_soc_dapm_mutex_lock(dapm); - if (ucontrol->value.integer.value[0] > CS40L26_A2H_VOLUME_MAX) - val = CS40L26_A2H_VOLUME_MAX; + if (ucontrol->value.integer.value[0] > CS40L26_A2H_LEVEL_MAX) + val = CS40L26_A2H_LEVEL_MAX; else if (ucontrol->value.integer.value[0] < 0) val = 0; else @@ -711,28 +711,27 @@ static int cs40l26_a2h_delay_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_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("A2H Level", 0, 0, CS40L26_A2H_LEVEL_MAX, 0, + cs40l26_a2h_level_get, cs40l26_a2h_level_put), + SOC_SINGLE_EXT("SVC Algo Enable", 0, 0, 1, 0, cs40l26_svc_en_get, + cs40l26_svc_en_put), SOC_SINGLE_EXT("Invert streaming data", 0, 0, 1, 0, cs40l26_invert_streaming_data_get, cs40l26_invert_streaming_data_put), SOC_SINGLE_EXT("I2S VMON", 0, 0, CS40L26_VMON_DEC_OUT_DATA_MAX, 0, cs40l26_i2s_vmon_get, NULL), - SOC_SINGLE_EXT("DSP Bypass", 0, 0, 1, 0, cs40l26_bypass_get, - cs40l26_bypass_put), + SOC_SINGLE_EXT("DSP Bypass", 0, 0, 1, 0, cs40l26_dsp_bypass_get, + cs40l26_dsp_bypass_put), SOC_SINGLE_EXT("A2H Delay", 0, 0, CS40L26_A2H_DELAY_MAX, 0, cs40l26_a2h_delay_get, cs40l26_a2h_delay_put), SOC_DOUBLE_EXT("RX Slots", 0, 0, 1, 63, 0, cs40l26_slots_get, cs40l26_slots_put), }; -static const char * const cs40l26_out_mux_texts[] = { "Off", "PCM", "A2H" }; +static const char * const cs40l26_out_mux_texts[] = { "None", "ASP Rx", "DSP Tx" }; static SOC_ENUM_SINGLE_VIRT_DECL(cs40l26_out_mux_enum, cs40l26_out_mux_texts); static const struct snd_kcontrol_new cs40l26_out_mux = - SOC_DAPM_ENUM("Haptics Source", cs40l26_out_mux_enum); + SOC_DAPM_ENUM("Haptics Streaming Source", cs40l26_out_mux_enum); static const struct snd_soc_dapm_widget cs40l26_dapm_widgets[] = { @@ -741,12 +740,12 @@ static const struct snd_soc_dapm_widget SND_SOC_DAPM_AIF_IN("ASPRX1", NULL, 0, SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_AIF_IN("ASPRX2", NULL, 0, SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_PGA_E("PCM", SND_SOC_NOPM, 0, 0, NULL, 0, cs40l26_pcm_ev, + SND_SOC_DAPM_PGA_E("ASP Rx", SND_SOC_NOPM, 0, 0, NULL, 0, cs40l26_asp_rx, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), - SND_SOC_DAPM_MIXER_E("A2H", SND_SOC_NOPM, 0, 0, NULL, 0, cs40l26_a2h_ev, + SND_SOC_DAPM_MIXER_E("DSP Tx", SND_SOC_NOPM, 0, 0, NULL, 0, cs40l26_dsp_tx, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), - SND_SOC_DAPM_MUX("Haptics Source", SND_SOC_NOPM, 0, 0, + SND_SOC_DAPM_MUX("Haptics Streaming Source", SND_SOC_NOPM, 0, 0, &cs40l26_out_mux), SND_SOC_DAPM_OUTPUT("OUT"), }; @@ -757,13 +756,13 @@ static const struct snd_soc_dapm_route { "ASPRX1", NULL, "ASP Playback" }, { "ASPRX2", NULL, "ASP Playback" }, - { "PCM", NULL, "ASPRX1" }, - { "PCM", NULL, "ASPRX2" }, - { "A2H", NULL, "PCM" }, + { "ASP Rx", NULL, "ASPRX1" }, + { "ASP Rx", NULL, "ASPRX2" }, + { "DSP Tx", NULL, "ASP Rx" }, - { "Haptics Source", "PCM", "PCM" }, - { "Haptics Source", "A2H", "A2H" }, - { "OUT", NULL, "Haptics Source" }, + { "Haptics Streaming Source", "ASP Rx", "ASP Rx" }, + { "Haptics Streaming Source", "DSP Tx", "DSP Tx" }, + { "OUT", NULL, "Haptics Streaming Source" }, }; static int cs40l26_component_set_sysclk(struct snd_soc_component *component, diff --git a/cs40l26/cs40l26-debugfs.c b/cs40l26/cs40l26-debugfs.c index 7a88847..5341d7d 100644 --- a/cs40l26/cs40l26-debugfs.c +++ b/cs40l26/cs40l26-debugfs.c @@ -214,6 +214,8 @@ void cs40l26_debugfs_init(struct cs40l26_private *cs40l26) struct dentry *root = NULL; int i; + cs40l26_debugfs_cleanup(cs40l26); + root = debugfs_create_dir("cs40l26", NULL); if (!root) return; @@ -230,18 +232,21 @@ void cs40l26_debugfs_init(struct cs40l26_private *cs40l26) cs40l26->dbg_fw_algo_id = CS40L26_VIBEGEN_ALGO_ID; cs40l26->debugfs_root = root; - cs40l26->cl_dsp_db = cl_dsp_debugfs_create(cs40l26->dsp, - cs40l26->debugfs_root, - (u32) CS40L26_EVENT_LOGGER_ALGO_ID); + if (cs40l26->fw_id == CS40L26_FW_ID) { + cs40l26->cl_dsp_db = cl_dsp_debugfs_create(cs40l26->dsp, + cs40l26->debugfs_root, + (u32) CS40L26_EVENT_LOGGER_ALGO_ID); - if (IS_ERR(cs40l26->cl_dsp_db) || !cs40l26->cl_dsp_db) - dev_err(cs40l26->dev, "Failed to create CL DSP Debugfs\n"); + if (IS_ERR(cs40l26->cl_dsp_db) || !cs40l26->cl_dsp_db) + dev_err(cs40l26->dev, "Failed to create CL DSP Debugfs\n"); + } } EXPORT_SYMBOL(cs40l26_debugfs_init); void cs40l26_debugfs_cleanup(struct cs40l26_private *cs40l26) { cl_dsp_debugfs_destroy(cs40l26->cl_dsp_db); + cs40l26->cl_dsp_db = NULL; kfree(cs40l26->dbg_fw_ctrl_name); cs40l26->dbg_fw_ctrl_name = NULL; debugfs_remove_recursive(cs40l26->debugfs_root); diff --git a/cs40l26/cs40l26.c b/cs40l26/cs40l26.c index 02be20f..97cdf4c 100644 --- a/cs40l26/cs40l26.c +++ b/cs40l26/cs40l26.c @@ -18,6 +18,24 @@ static inline bool section_complete(struct cs40l26_owt_section *s) return s->delay ? true : false; } +static u32 gpio_map_get(struct device_node *np, enum cs40l26_gpio_map gpio) +{ + const char *bank, *name = gpio == CS40L26_GPIO_MAP_A_PRESS ? + "cirrus,press-index" : "cirrus,release-index"; + u32 val; + + if (!of_property_read_string_index(np, name, 0, &bank) && + !of_property_read_u32_index(np, name, 1, &val)) { + if (!strncmp(bank, "RAM", 3)) + return (val & CS40L26_BTN_INDEX_MASK) | + (1 << CS40L26_BTN_BANK_SHIFT); + else if (!strncmp(bank, "ROM", 3)) + return val & CS40L26_BTN_INDEX_MASK; + } + + return CS40L26_EVENT_MAP_GPI_DISABLE; +} + static int cs40l26_dsp_read(struct cs40l26_private *cs40l26, u32 reg, u32 *val) { struct regmap *regmap = cs40l26->regmap; @@ -3197,10 +3215,6 @@ static int cs40l26_input_init(struct cs40l26_private *cs40l26) } #endif - #ifdef CONFIG_DEBUG_FS - cs40l26_debugfs_init(cs40l26); - #endif - cs40l26->vibe_init_success = true; return ret; @@ -3308,6 +3322,20 @@ static int cs40l26_gpio_config(struct cs40l26_private *cs40l26) else val = 0; + ret = regmap_write(cs40l26->regmap, CS40L26_A1_EVENT_MAP_1, + cs40l26->pdata.press_idx); + if (ret) { + dev_err(cs40l26->dev, "Failed to map press GPI event\n"); + return ret; + } + + ret = regmap_write(cs40l26->regmap, CS40L26_A1_EVENT_MAP_2, + cs40l26->pdata.release_idx); + if (ret) { + dev_err(cs40l26->dev, "Failed to map release GPI event\n"); + return ret; + } + return cs40l26_irq_update_mask(cs40l26, CS40L26_IRQ1_MASK_1, val, mask); } @@ -3927,6 +3955,10 @@ static int cs40l26_dsp_config(struct cs40l26_private *cs40l26) cs40l26->fw_loaded = true; +#ifdef CONFIG_DEBUG_FS + cs40l26_debugfs_init(cs40l26); +#endif + ret = cs40l26_pseq_init(cs40l26); if (ret) return ret; @@ -4806,6 +4838,9 @@ static int cs40l26_handle_platform_data(struct cs40l26_private *cs40l26) else cs40l26->pdata.pwle_zero_cross = false; + cs40l26->pdata.press_idx = gpio_map_get(np, CS40L26_GPIO_MAP_A_PRESS); + cs40l26->pdata.release_idx = gpio_map_get(np, CS40L26_GPIO_MAP_A_RELEASE); + return cs40l26_no_wait_ram_indices_get(cs40l26, np); } @@ -4995,9 +5030,9 @@ int cs40l26_remove(struct cs40l26_private *cs40l26) #endif } - #ifdef CONFIG_DEBUG_FS +#ifdef CONFIG_DEBUG_FS cs40l26_debugfs_cleanup(cs40l26); - #endif +#endif if (cs40l26->input) input_unregister_device(cs40l26->input); diff --git a/cs40l26/cs40l26.h b/cs40l26/cs40l26.h index 4f3e271..765bd28 100644 --- a/cs40l26/cs40l26.h +++ b/cs40l26/cs40l26.h @@ -1183,7 +1183,7 @@ #define CS40L26_A2H_MAX_TUNINGS 5 -#define CS40L26_A2H_VOLUME_MAX 0x7FFFFF +#define CS40L26_A2H_LEVEL_MAX 0x7FFFFF #define CS40L26_A2H_DELAY_MAX 0x190 @@ -1274,7 +1274,7 @@ #define CS40L26_COMP_EN_F0_SHIFT 0 /* FW EXT */ -#define CS40L26_SVC_FOR_STREAMING_MASK BIT(0) +#define CS40L26_SVC_EN_MASK BIT(0) /* DBC */ #define CS40L26_DBC_ENABLE_MASK BIT(1) @@ -1483,6 +1483,8 @@ struct cs40l26_platform_data { bool dbc_enable_default; u32 dbc_defaults[CS40L26_DBC_NUM_CONTROLS]; bool pwle_zero_cross; + u32 press_idx; + u32 release_idx; }; struct cs40l26_uploaded_effect { @@ -1555,13 +1557,13 @@ struct cs40l26_private { unsigned int svc_le_est_stored; u32 *no_wait_ram_indices; ssize_t num_no_wait_ram_indices; - #ifdef CONFIG_DEBUG_FS +#ifdef CONFIG_DEBUG_FS struct dentry *debugfs_root; char *dbg_fw_ctrl_name; u32 dbg_fw_algo_id; bool dbg_fw_ym; struct cl_dsp_debugfs *cl_dsp_db; - #endif +#endif }; struct cs40l26_codec { @@ -1576,7 +1578,7 @@ struct cs40l26_codec { int tdm_width; int tdm_slots; int tdm_slot[2]; - bool bypass_dsp; + bool dsp_bypass; }; struct cs40l26_pll_sysclk_config { diff --git a/cs40l26/cs40l26.yaml b/cs40l26/cs40l26.yaml index f9f796b..6e1a683 100644 --- a/cs40l26/cs40l26.yaml +++ b/cs40l26/cs40l26.yaml @@ -447,6 +447,16 @@ cirrus,no-wait-ram-indices: List of RAM indices that will not use the delay_before_stop_playback_us prior to sending a STOP_PLAYBACK command. +cirrus,release-index: + descrption: + Bank and index of effect to be mapped to GPI release event upon driver + probe. + +cirrus,press-index: + description: + Bank and index of effect to be mapped to GPI press event upon driver + probe. + required: - compatible @@ -481,6 +491,9 @@ examples: cirrus,no-wait-ram-indices = <5 10 25>; + cirrus,release-index = "RAM", <1>; + cirrus,press-index = "ROM", <2>; + svc-le1 { cirrus,min = <500>; //59.6 uH cirrus,max = <750>; //89.4 uH |